ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

スワイプでページ送りできるタブ付きの Android Activity を作る

スワイプでページ送りができて、Activity 上部にタブでページ名が並んでいる (もちろんタップしたらそのページに移動する) というような Activity を作る方法です。

サンプルのスクリーンショット

次のような感じです。

f:id:nobuoka:20131020232611p:plain

タブ部分をスワイプしたら、タブに並んでるページ名の隠れてる部分を見れるし、コンテンツ部分をスワイプしたら次のページや前のページに戻ります。 タブのページ名をタップすると、そのページに移動します。

IDE でひな形を生成する

このような Activity の雛形は IDE (EclipseAndroid Studio) の機能で生成することができます。

Android Studio (0.3.0 現在) の場合、ソースディレクトリ内のパッケージを右クリックして、「New」 から 「Activity」 を選択します。

f:id:nobuoka:20131020233251p:plain

「New Activity」 を選択し、「Next」 に行きます。

f:id:nobuoka:20131020233412p:plain

「Navigation Type」 として 「Action Bar Tabs (with Viewer Pager)」 を選択します。 あとは 「Acticity Name」 などを適当に入力して 「Finish」 ボタンを押せば、スワイプでページ送りできるタブ付きの Activity の雛形が生成されます。

詳細

詳細は次の参考資料に書いてあります。

スワイプでページ送りするためのビュー

重要なのは v4 support library に含まれている ViewPager ウィジェット です。 これを使えばスワイプでページ送りができます。 ページ自体は Fragment で表されます。

ListView に対する ListAdapter のように、ViewPager 上に表示するコンテンツを管理するものとして PagerAdapter を使用します。 PagerAdapter には次の 2 種類があります。

  • FragmentPagerAdapter: 固定個数の小数のページ間のナビゲーションに最適である
  • FragmentStatePagerAdapter: ページの個数が決まっていない場合 (?) に最適 *1。 メモリ使用量を小さくするために、ユーザーが別のページに移ったときに Fragment を破棄します。

Android Studio で作った雛形だと FragmentPagerAdapter が使われていたのですが、実際に画像をいくつも表示するようなページを 10 個ぐらい扱うとメモリが足りなくなってしまったので、必要に応じて FragmentStatePagerAdapter を使うようにする必要があるでしょう。

タブを表示する

タブは Action bar に表示されます。 タブを追加したり、ページ遷移時に active なタブを切り替えたりする必要がありますが、IDE でひな形を作った場合はもともとそれらの処理は書かれているので特にいじる必要はないでしょう。

タブの代わりにタイトル片を使用する

Action bar 上のタブを使うのではなく、現在のページ名と前後のページ名を表示させたいような場合は PagerTitleStrip を使用できます。 (もちろん Action bar 上のタブとも併用できますが意味はないでしょう。)

次のように、ViewPager の中に PagerTitleStrip を入れるだけで実現できます。

<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v4.view.PagerTitleStrip
        android:id="@+id/pager_title_strip"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:background="#33b5e5"
        android:textColor="#fff"
        android:paddingTop="4dp"
        android:paddingBottom="4dp" />

</android.support.v4.view.ViewPager>

*1:『This is best for paging across a collection of objects for which the number of pages is undetermined.』 が元の英語。