woshidan's blog

あいとゆうきとITと、とっておきの話。

Mixi Android Training 第5回分の参考資料の演習についてメモ2

ListViewの5がちょっときつかったです。

まとめ

この範囲の演習で大事そうだと思った事を先にまとめ

  • Android Studioで非Android Studioのプロジェクトを読み込む時は、専用のメニューから
  • ContextMenu(Androidにおいて、長押し時に表示されるメニュー)の操作の仕方
    • http://woshidan.hatenadiary.jp/entry/2015/05/05/224220
    • Activity#onResume() などで registerForContextMenu(mTargetView); にて登録する
    • イベントリスナの削除は、unregisterForContextMenu(mTargetView);
    • onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo)
      • getMenuInflater().inflate(R.menu.context_menu_main, menu);でContextMenuのレイアウト用のxmlを指定できる
    • onContextItemSelected(MenuItem item) が呼び出される
      • item.getItemId()を使ってActivity内のどの要素の長押しで呼び出されたのか特定する
        • ここのIdはxmlファイルに書いたIdっぽい。 cf: R.id.DeleteListItem
      • ContextMenuInfoはContext Menuの作成に関する追加情報を扱うクラス
        • たとえば、AdapterViewがContextMenuを発生するViewとして登録されていた場合、このクラスは、Adapterで扱っているコレクションの中のどのアイテムを長押しする事でタップしているか、といった情報を持っている。
  • Fragmentをスワイプして切り替える感じのUIを作る時はFragmentPagerAdapterを利用
    • FragmentはnewInstance()メソッド(インスタンスのFactoryメソッド)とonCreateView()(レイアウトに受け取った情報を元にテキスト等差し替え)メソッドを実装する
    • FragmentPagerAdapterはFragmentManagaerを利用
    • Pager部分のXMLはMainActibityのXMLに組み込んでおく
  • Tab Nabigationを使うときは、ActionBarクラスのインスタンスを作り、ActionBar.NAVIGATION_MODE_TABS を有効にする
    • Pager側にsetOnPageChangeListenerを実装する
    • actionBar側にtabListenerを実装する
    • タブを追加する時は、actionBar.addTabで、引数に追加したいタブを入れる

以下、演習日記的なメモ。

4までSampleの方をいじっていて、課題ファイルが綺麗な状態だったので、

  • BookArrayAdapterの作成
  • BookActivityの作成

もせっかくなのでやり直したあと、ListViewの課題5に入りました。

ListView

5 (課題)

課題3のContextMenuにListViewが設定されています。ContextMenuには追加と削除メニューが定義されています。追加をタップしたときは選択されているアイテムを新たなアイテムとしてListViewにデータを追加してください。削除をタップしたときは選択されているアイテムを削除するように実装してください。
ヒント:データの追加、削除、表示の更新処理はAdapterで行います。

とりあえず、課題用プロジェクトファイルを見て、

// MainActivity
@Override
protected void onResume() {
    super.onResume();
    registerForContextMenu(mListView);
}
// MainActivity
@Override
protected void onPause() {
    super.onPause();
    unregisterForContextMenu(mListView);
}

でContextMenuの登録がどこでされているかを確認。

で、Activity#onContextItemSelected()については細かくは、 http://woshidan.hatenadiary.jp/entry/2015/05/05/224220 にて確認したので、

// public boolean onContextItemSelected(MenuItem item) 内
if (item.getItemId() == R.id.DeleteListItem) {
    // TODO:Adapterを使用して長押ししたデータを削除してください
    adapter.remove(book);
} else if (item.getItemId() == R.id.AddListItem) {
    // TODO:Adapterを使用して長押ししたデータを追加してください
    adapter.add(book);
}
// TODO:Adapterを使用して表示されているデータを更新してください
mListView.setAdapter(adapter);

こういう感じに書きました。

ViewPager

1 (実習)

FragmentPagerAdapter の使い方で説明したプロジェクトを写経して実行してください。説明したプロジェクトはAndroidTraining/projects/fundamentals/6th/FragmentViewPagerSampleにあります。

写経した時のメモ

  • Fragment#newInstance(int position)Fragment#onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) の違い
    • Fragment#newInstance(int position)SampleFragmentPagerAdapter#getItem()にて利用される
      • Fragment#setArguments(Bundle bundle) を利用する事と関係あるのかもしれない
      • 位置の挿入だけが行われている
      • Factoryメソッドの利用
        • PagerAdapterクラスはPagerの詳細を知らずに利用できる?
    • Fragment#onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) は表示するテキストを挿入したりして、具体的にViewを作成する。
    • Pagerの情報はbundleで管理されているっぽい
  • FragmentPagerAdapterはFragmentManagerを利用
  • Pager部分の枠の要素のXMLはMainActibity(Pagerを入れたいActivity)のXMLに組み込んでおく

2 (課題)

実習1のプロジェクトを引き続き使用してください。ActionBarのTab Navigationを追加し、Tabを選択したら該当のページが表示されるようにしてください。(3番目のTabを選択したら3ページ目が表示される)また、ページをスクロールさせたら該当のTabが選択されるようにしてください。 また、Tabとページの数は3つとしてください。

TabNavigationの追加の仕方は何だっけ。iOSなら検討つくかもしれないのだけどな(笑)。

とか阿呆な事言っていても仕方が無いので、

http://developer.android.com/training/implementing-navigation/lateral.html

あたりを見ます。

この辺を読んでいて、追加メモ

  • FragmentPagerAdapterは固定ページでページ数が少ないときに良いらしい
  • ページ数が多かったり不定な時はFragmentStatePagerAdapterを使うと良いらしい

TabNavigationを利用するためには、ActionBarを使い、NAVIGATION_MODE_TABSを有効状態にする必要があります。 そして、いくつか ActionBar.Tabインスタンスを作成して、それぞれにActionBar.TabListenerのインタフェースを実装します。onCreate()あたりで。

などを読んで、実装した結果が下記。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // http://developer.android.com/guide/topics/ui/actionbar.html
    // SDKの11より低いバージョンにも対応したい場合はサポートライブラリを使う
    // 面倒くさかったので、manifestをいじってSDKの対応最小バージョンを11に上げています
    final ActionBar actionBar = getActionBar();

    // Tabがアクションバーの位置に表示される事を指定する
    // 他にはドロップダウンリストを作るためのNAVIGATION_MODE_LIST
    // などがあるが、いまは、Action bar navigation modesはdeprecatedとなっており、
    // ナビゲーション方法に関してもっと一般的な下記のパターンを使ってみては、とのリンクが
    // http://developer.android.com/design/patterns/navigation.html
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    setContentView(R.layout.activity_main);

    final ViewPager pager = (ViewPager) findViewById(R.id.Pager);

    // Tabによってページの切り替えをしたい場合
    // ViewPager側にはsetOnPageChangeListenerメソッドの実装が必要
    // それにしても上記のfinalの修飾子はこれでいいのか...
    pager.setOnPageChangeListener(
            new ViewPager.SimpleOnPageChangeListener() {
                @Override
                public void onPageSelected(int position) {
                    // When swiping between pages, select the
                    // corresponding tab.
                    getActionBar().setSelectedNavigationItem(position);
                }
            }
    );
    
    FragmentManager fm = getSupportFragmentManager();
    SampleFragmentPagerAdapter sampleFragmentPagerAdapter = new SampleFragmentPagerAdapter(fm);
    
    pager.setAdapter(sampleFragmentPagerAdapter);

    // タブのイベントリスナを作ります
    ActionBar.TabListener tabListener = new ActionBar.TabListener() {
        public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
            // show the given tab
            // Tabをクリックしたら該当するタブの位置のページへ切り替えたい場合
            pager.setCurrentItem(tab.getPosition());
        }

        public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
            // hide the given tab
        }


        public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
            // probably ignore this event
        }
    };

    // Tabを追加します。本当はもうちょっと考えて追加すると思うんですが
    // 今回はこれでいいかな感あります
    for (int i = 0; i < 5; i++) {
        actionBar.addTab(
                actionBar.newTab()
                        .setText("Tab " + (i + 1))
                        .setTabListener(tabListener)
        );
    };
};