SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Web APIで楽々Androidアプリ

Androidアプリでのタブレット用2ペイン表示

Web APIで楽々Androidアプリ(8)

  • X ポスト
  • このエントリーをはてなブックマークに追加

ArrayAdapterを利用する

 EkiListFragmentにデータをセットするタイミングは、Web APIから結果を受信した後です。ですから、MainActivityのonLoadFinishedメソッドに、次のようなコードを追加しましょう。

MainActivity.javaのonLoadFinishedメソッド
@Override
public void onLoadFinished(Loader<String> loader, String body) {
    if (body == null) return;

    switch (loader.getId()) {
    case 0:
        // APIの結果を解析する
        ParseMoyori parse = new ParseMoyori();
        parse.loadJson(body);

       ~中略~

        // 駅情報のアダプターを作成する(1)
        ArrayAdapter<EkiInfo> adapter =
            new ArrayAdapter<EkiInfo>(this,
                                      android.R.layout.simple_list_item_1,
                                      parse.getEkiinfo());
        try {
            ListFragment listFragment =
                (ListFragment)fm.findFragmentById(R.id.eki_list);

            // ListFragmentに駅情報のアダプターを設定する(2)
            listFragment.setListAdapter(adapter);
        }
        catch (Exception e) {
        }
        break;
    }
}

 受信したデータから、ArrayAdapterオブジェクトを生成します(1)。ArrayAdapterのコンストラクタはいくつかありますが、ここでは次のコンストラクタを適用しています。

[構文]ArrayAdapterのコンストラクタ
public ArrayAdapter (Context context, int resource, List<T> objects)
  • context コンテキスト
  • resource リソースID(TextView)
  • objects セットしたいオブジェクト

 第2引数で指定するリソースIDとは、ListViewウィジェットの1行を表示しているTextViewウィジェットのものです。ListFragmentのデフォルトでは、simple_list_item_1という名前のIDになっています。

 第3引数には、Listコレクションのオブジェクトを指定します。(1)で記述しているParseMoyoriクラスのgetEkiinfoメソッドは、フィールドのList<EkiInfo>オブジェクトを参照するものです。

 作成したアダプターをListFragmentに設定するには、ListFragmentクラスに用意されたsetListAdapterメソッドを実行します(2)。これだけで、一覧表示されるようになります。

 なお、EkiInfoオブジェクトから、テキスト表示へ変換するために、toStringメソッドをオーバーライドしておきます。これで、駅名(路線名)という表示になります。

EkiInfo.javaの一部
//最寄駅情報クラス
public class EkiInfo {
    ~中略~
    @Override
    public String toString() {
        return name + "(" + line + ")";
    }
}

フラグメントにクリックのコールバックメソッドを追加する

 次に、最寄り駅名をタップしたときの処理を追加しましょう。これは、コールバックされるonListItemClickメソッドをオーバーライドするだけです。オーバーライドすれば、リストの項目がタップされたときの処理を記述することができます。

EkiListFragment.javaのonListItemClickメソッド
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);

    try {
        // クリックした行の駅情報を取得(1)
        EkiInfo e = (EkiInfo)getListAdapter().getItem(position);

        MyMapFragment mapFragment =
            (MyMapFragment)getFragmentManager().findFragmentById(R.id.map);

        // 駅情報に合致するマーカーの情報ウィンドウを表示し地図を移動する(2)
        mapFragment.moveEkiToCenter(e);
    }
    catch (Exception e) {
    }
}

 onListItemClickメソッドの第3引数には、クリックされた項目が上から何番目なのかという情報がセットされています。この情報をもとに、該当の駅のEkiInfoオブジェクトを取得しています(1)

 (2)のmoveEkiToCenterメソッドは、後述するMyMapFragmentに追加するメソッドです。駅情報に合致するマーカーの情報ウィンドウを表示して、地図の中心をその駅に移動する処理となっています。

moveEkiToCenterメソッドを実装する

 では最後に、MyMapFragmentにmoveEkiToCenterメソッドを追加しましょう。また、このメソッドの追加にともない、前回のコードの変更とフィールドの追加があります。

MyMapFragment.javaの一部
public class MyMapFragment extends MapFragment {
    ~中略~

    // API実行の抑制フラグ(1)
    private Boolean noCameraChange = false;

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        try {
            // 地図を移動したときのリスナー
            googleMap.setOnCameraChangeListener(new OnCameraChangeListener() {
                @Override
                public void onCameraChange(CameraPosition cameraPosition) {

                    // noCameraChangeがtrueならWeb APIを呼び出さない(2)
                    if (0.5 < calcDistance(centerPosition,cameraPosition) &&
                                                             !noCameraChange) {
                        execMoyori(cameraPosition);
                        centerPosition = cameraPosition;
                    }
                    noCameraChange = false; // デフォルトに戻す
                }
            });
        }
        ~中略~
    }

    // 駅情報からマーカーを求める(4)
    public Marker getKeyByValue(EkiInfo value) {
        for (Entry<Marker, EkiInfo> entry : ekiMarkerMap.entrySet()) {
            if (value.equals(entry.getValue())) {
                return entry.getKey();
            }
        }
        return null;
    }

    // 駅情報に合致するマーカーの情報ウィンドウを表示し、地図の中心にする
    public void moveEkiToCenter(EkiInfo value) {

        Marker marker = getKeyByValue(value); // 駅情報からマーカーを取得(3)
        marker.showInfoWindow();              // 情報ウィンドウを表示(5)

        // マーカーの位置に地図の中心を移動する(6)
        CameraPosition cameraposprev = googleMap.getCameraPosition();
        CameraPosition camerapos = 
            new CameraPosition.Builder(cameraposprev)
                                       .target(marker.getPosition()).build();
        noCameraChange = true;
        googleMap.animateCamera(              // (7)
            CameraUpdateFactory.newCameraPosition(camerapos));
    }
    ~後略~
}

 フィールドに、 API実行の抑制フラグを追加しています(1)。これは、コードで地図の中心を移動させたときに、意図せずWeb APIが実行されないようにするためです(2)。また、自分で地図を移動させた場合(フラグがfalseのとき)のみ、最寄り駅情報が更新されるようにしています。

 moveEkiToCenterメソッドでは、まずEkiInfoオブジェクトから、マーカーオブジェクトを取得しています(3)。EkiInfoオブジェクトとマーカーオブジェクトは、ekiMarkerMapというHashMapコレクションに保存していますので、getKeyByValueメソッドのなかで、forループを使って1つずつEkiInfoを比較し、マーカーオブジェクトを検索しています(4)

 マーカーオブジェクトが取得できれば、showInfoWindowメソッドで情報ウィンドウを表示し(5)、地図を移動させます(6)

 地図の中心をマーカーの位置に移動させるには、CameraPositionオブジェクトを作成します。これは、GoogleMapクラスのanimateCameraメソッドを利用しています。animateCameraメソッドは、瞬時に切り替わるmoveCameraメソッドとは異なり、地図の移動をアニメーションしながら行うものです。

最後に

 今回は、最寄り駅の一覧を表示するFragmentを追加して、2ペイン表示する方法を解説しました。次回は、地図表示の上に、最寄り駅の一覧をオーバーラップさせるスマートフォン用の画面を解説します。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Web APIで楽々Androidアプリ連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 高江 賢(タカエ ケン)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/7615 2014/02/20 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング