ほげほげ(仮)

仮死状態

WebViewの長押しのイベントを取得する


通常のブラウザのように長押しで画像の保存等を行うには次のようにやります。

mWebView.setOnLongClickListener(new OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        WebView webView = (WebView) v;
        WebView.HitTestResult hr = webView.getHitTestResult();
        String url = hr.getExtra();
        Log.d("WebView LogClick", url);
        return false;
    }
});


onLongClickでViewからWebView.HitTestResultで長押しされている箇所のURLが取得できます。

自分が確認できたのはリンクと画像でイベントが走りました。


これを使えば長押しされている画像やリンクに対して処理が可能となります。

修正

すいません、2.2以前では画像だけではイベントは走りませんでした。リンクが貼ってある画像だけですね。

バージョンが2.3以降の場合はイベントが取得できるようになっています。
軽くメモしておきました。WebViewの長押しイベントについて(2.3以降) - 全力で気まぐれ

DatePickerDialogのタイトル


次のようにDatePickerDialogを使うと

// 今日の日付を取得
Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
// DatePickerDialogを表示
DatePickerDialog datePickerDialog = new DatePickerDialog(mActivity, null, year, month, day);
datePickerDialog.show();


下のようなダイアログが表示されますが、日付を変えるたびに赤枠のところも変わってしまいます。
書式とかも指定ができません。
f:id:STAR_ZERO:20101018234251p:image




もし、この動きがイヤな場合はDatePickerを使ってダイアログを自作することで可能です。

// AlertDialog.Builderを生成
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
// DatePickerを生成
DatePicker datePicker = new DatePicker(mActivity);
// ViewにDatePickerを設定
builder.setView(datePicker);
// タイトルを設定(今日の日付)
builder.setTitle("日付選択");
// Setボタンを設定
builder.setPositiveButton("Set", null);
// Cancelボタンを設定
builder.setNegativeButton("Cancel", null);
// AlertDialogを生成
AlertDialog alertDialog = builder.create();
// AlertDialogを表示
alertDialog.show();


上のように書くと下のようになり、日付を変更してもタイトルは変更されません。
例ではsetPositiveButtonとsetNegativeButtonの第二引数にnullを設定していますが、SetボタンとCancelボタンのイベントをココに書くようにしてください。
f:id:STAR_ZERO:20101019000022p:image




DatePickerのinitメソッドを使えば、初期値と変更時のイベント行うことが出来ます。

// 今日の日付を取得
Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);
// AlertDialog.Builderを生成
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
// DatePickerを生成
DatePicker datePicker = new DatePicker(mActivity);
builder.setView(datePicker);
// タイトルを設定(今日の日付)
builder.setTitle(String.valueOf(year) + "/" + String.valueOf(month + 1) + "/" + String.valueOf(day));
builder.setPositiveButton("Set", null);
builder.setNegativeButton("Cancel", null);
final AlertDialog alertDialog = builder.create();
alertDialog.show();
// 初期値と変更時のイベントを設定
datePicker.init(year, month, day, new DatePicker.OnDateChangedListener() {
    @Override
    public void onDateChanged(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
        alertDialog.setTitle(String.valueOf(year) + "/" + String.valueOf(monthOfYear + 1) + "/" + String.valueOf(dayOfMonth));
    }
});

最後のinitでDatePickerが変更されるたびにタイトルがyyyy/m/dで表示されるようにしています。

f:id:STAR_ZERO:20101019002654p:image


DatePickerドキュメント
DatePicker | Android Developers

AndroidでGPSを使ってみる


AndroidでGPSを使った簡単サンプルを使ってみました。

今回はロケーションが変更されるたびにマップの表示を変更しています。


以前書いたGoogleMapのサンプルに若干の修正を入れました。


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.sample.map"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".Sample"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <uses-library android:name="com.google.android.maps"/>
    </application>

    <uses-permission android:name="android.permission.INTERNET"/>

    <!-- アプリケーションがGPSへアクセスするのを許容 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <!-- アプリケーションがテスト用の位置情報にアクセスするのを許容 -->
    <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />

    <uses-sdk android:minSdkVersion="4" />
</manifest>

今回は2箇所追加しています。



ACCESS_MOCK_LOCATIONのほうはエミュレーター用なので実機の場合は不要です。


Sample.java

package com.sample.map;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class Sample extends MapActivity implements LocationListener {

    private MapController mController;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // MapViewを取得
        MapView mapView = (MapView) findViewById(R.id.mapview);

        // 拡大・縮小ボタンを表示
        mapView.setBuiltInZoomControls(true);

        // LocationManagerを取得
        LocationManager l = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        // LocationManagerにリスナーを登録
        l.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);

        // コントローラーをフィールドに設定
        mController  = mapView.getController();

    }

    @Override
    protected boolean isRouteDisplayed() {
        return false;
    }

    public void onLocationChanged(Location location) {
        // 現在地を取得
        GeoPoint gp = new GeoPoint((int)(location.getLatitude()*1E6), (int)(location.getLongitude()*1E6));
        // コントローラーを使用して、現在地にマップを移動
        mController.animateTo(gp);
    }

    public void onProviderDisabled(String provider) {
    }

    public void onProviderEnabled(String provider) {
    }

    public void onStatusChanged(String provider, int status, Bundle extras) {
    }
}

まずはLocationListenerを実装します。
今回の場合は位置が変更されたときなので、onLocationChangedというメソッドを使用します。
これはロケーションが変更された時に呼び出されます。


onCreateメソッドでリスナーの登録を行ないます。
ActivityクラスのgetSystemServiceメソッドでLocationManagerを取得し、LocationManagerにリスナーを登録しています。


修正内容としてはこれだけです。

さっそく動かしてみます。
f:id:STAR_ZERO:20100725210011p:image


これだけでは意味はないので、次にGPS情報を設定します。
エミュレーターを動かしている状態で、eclipseのメニューから「ウィンドウ」→「ビューの表示」→「その他」を選択します。
f:id:STAR_ZERO:20100725210012p:image
Android」→「Emulator Control」を選択します。


f:id:STAR_ZERO:20100725211458p:image

Emulator Controlの赤丸の場所を入力して送信ボタンを押します。
上の例では
Longitude:139.70154762268066
Latitude:35.6581679808236
渋谷駅付近を設定しています。


送信ボタンを押すと、エミュレターでは渋谷駅に移動しているはずです。
f:id:STAR_ZERO:20100725211747p:image


あまり難しいことはしていませんが、細かい部分をまだ調べきれていないので
どっか時間があるときandやる気のある時に調べてみようと思います。

Androidのコーディング規約


Androidのコーディング規約ないかなぁって探したらありました。


Code Style Guidelines for Contributors


日本語に訳されたのもありました。

コントリビュータのためのAndroidコードスタイルガイドライン 日本語訳


このコードスタイルを見て、どーしても気になるのがフィールド名のプレフィックスが「m」っていうところ。

ツイッターのフォローさん曰くC++でよく見かけるものらしいです。ただ、Androidでなぜ採用されたかは謎らしいです。


この部分がJavaっぽくないなぁって思うんだよねぇ・・・

ListActivityでハマった


ListViewを試そうと思っていろいろ試してたんだけど、

ListActivityを継承したままで、レイアウトxmlからListViewを削除したらエラーが出て起動すらしなくなった。


レイアウトxmlにListViewがない状態でListActivityを継承したActivityで

setContentViewの箇所でエラーになるみたいです。


当たり前と言えば当たり前ですね・・・


これ気づくのに2時間かかったオレって・・・

Androidでメニューを表示する

Androidでメニューを表示する方法を簡単にまとめてみました。

メニューを表示してみる

Activityを継承しているクラスでonCreateOptionsMenuメソッドをオーバーライドして、メニューを追加します。

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;

public class Sample extends Activity {

    private static final int MENU_ID1 = Menu.FIRST;

    private static final int MENU_ID2 = Menu.FIRST + 1;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        menu.add(Menu.NONE, MENU_ID1, Menu.NONE, "Menu1");
        menu.add(Menu.NONE, MENU_ID2, Menu.NONE, "Menu2");
        return super.onCreateOptionsMenu(menu);
    }

}


これを実行して、メニューボタンを押すとメニューが表示されます。
f:id:STAR_ZERO:20100711130549p:image

メニューが選択されたときに処理をする

メニューが選択されたときに処理をするにはonOptionsItemSelectedメソッドをオーバーライドします。
引数に選択されたメニューIDが渡されるので、それによって処理を分けます。
下の例ではダイアログを表示しています。

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        AlertDialog.Builder dialog = new AlertDialog.Builder(this);

        switch (item.getItemId()) {
        case MENU_ID1:
            dialog.setMessage("メニュー1");
            dialog.show();
            return true;

        case MENU_ID2:
            dialog.setMessage("メニュー2");
            dialog.show();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }


実行してメニューを選択すると下のようにダイアログが表示されます。
f:id:STAR_ZERO:20100711131550p:image

メニューにアイコンを表示してみる

メニューにアイコンを表示するには、MenuItemクラスのsetIconメソッドでアイコンを指定します。
先ほどのonCreateOptionsMenuメソッドを下のように変更します。

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuItem item1 = menu.add(Menu.NONE, MENU_ID1, Menu.NONE, "Menu1");
        MenuItem item2 = menu.add(Menu.NONE, MENU_ID2, Menu.NONE, "Menu2");
        item1.setIcon(android.R.drawable.ic_menu_add);
        item2.setIcon(android.R.drawable.ic_menu_preferences);
        return super.onCreateOptionsMenu(menu);
    }


実行してメニューを表示するとアイコンが追加されています。
f:id:STAR_ZERO:20100711132923p:image


今回使ったアイコンはAndroidが持っているシステムアイコンを使用しています。
他にどんなアイコンがあるかはココが参考になると思います。

GoogleMapの拡大・縮小

f:id:STAR_ZERO:20100704221316p:image
↑のように Android で GoogleMap の拡大・縮小のボタンを出すやりかた。

これが意外と簡単で次のように書くだけ。

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // MapViewを取得
        MapView mapView = (MapView) findViewById(R.id.mapview);
        // 拡大・縮小ボタンを表示
        mapView.setBuiltInZoomControls(true);

    }

GoogleMap の View を取得して setBuiltInZoomControls メソッドを引数に true 設定して呼ぶだけ!

実はコレに気づくまで、オレはチマチマとボタンを作ったりしようとしてた。

参考はこちら → Google Map View