Androidのチュートリアル – Tutorials > Hello, Views | Tab Layout

Tab Layout は複数ページを切り替えるタブを持ったコンテナです。

アクティビティ作成

HelloTabLayout という名前で新規にプロジェクトをつくります。

各画面用のアクティビティの ArtistsActivity、AlbumsActivity、SongsActivity 三つを作成します。

以下のサンプルをつくりました。クラス名と表示文字列を変えただけですけど。

src/ 以下のパッケージに追加で作成してください。

package com.example;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class ArtistsActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView textview = new TextView(this);
        textview.setText("This is the Artists tab");
        setContentView(textview);
    }
}
package com.example;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class AlbumsActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView textview = new TextView(this);
        textview.setText("This is the Albums tab");
        setContentView(textview);
    }
}
package com.example;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class SongsActivity extends Activity {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TextView textview = new TextView(this);
        textview.setText("This is the Songs tab");
        setContentView(textview);
    }
}

各タブを選択したときの各アクティビティを作成しました。

StateListDrawable の作成

タブに表示される画像を設定します。

ここでは選択中と非選択中のタブ用の二つの画像を用意します。

チュートリアルのページには artists 用のオン・オフ用タブ画像が、img要素で貼り付けてありますが、これも含めて、albums と songs 用のアイコン画像のダウンロードは用意されていないようです(あるのかな?見つけられませんでした)。

なので、以下 artists 用画像の直リンですが、albums と songs にファイル名を変えて、res/drawable/ 以下に保存してください。

drawable というディレクトリがなければ作ってください。

StateListDrawable とは、それら二つの画像をタブのステータス(選択・非選択)によって切り替わる画像の割り当てリストです。

res/drawable/ic_tab_artists.xml を作成します。同様に、albums、songs も作成します。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- When selected, use grey -->
    <item android:drawable="@drawable/ic_tab_artists_grey"
          android:state_selected="true" />
    <!-- When not selected, use white-->
    <item android:drawable="@drawable/ic_tab_artists_white" />
</selector>

この定義を置くことで、タブに表示される画像が、選択・非選択でさし変わります。

タブレイアウトの作成

レイアウト定義 res/layout/main.xml にコピペします。

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="5dp">
        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:padding="5dp" />
    </LinearLayout>
</TabHost>

TabHost は TabWidget と FrameLayout を子要素以下に持つ必要があります。

FrameLayout の中に、タブで選択されたアクティビティが描画されるので、中身は空になってます。

少し注意を払うなら、TabWidget に tabs 、FrameLayout に tabcontent という ID がそれぞれつけられていることです。

これらは、TabHost から操作できるように、名前をつけておく必要があります。

継承元クラスを変更する

タブを扱う場合は、メインのアクティビティの継承元を TabActivity にします。

import android.app.TabActivity;
import android.os.Bundle;

public class TabLayoutActivity extends TabActivity {
...
}

初期化時のコードを修正

onCreate() でタブやアクティビティの初期化をします。

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

    Resources res = getResources(); // Drawable から取得するためのリソースオブジェクト
    TabHost tabHost = getTabHost();  // TabHost のアクティビティを取得
    TabHost.TabSpec spec;  // 各タブの処理で使いまわす TabSpec 型の変数
    Intent intent;  // 各タブの処理で使いまわす Intent 型の変数

    // タブに呼び出すアクティビティのインテントを生成
    intent = new Intent().setClass(this, ArtistsActivity.class);

    // TabHost に追加する Artists の TabSpec を用意する。
    spec = tabHost.newTabSpec("artists").setIndicator("Artists",
                      res.getDrawable(R.drawable.ic_tab_artists))
                  .setContent(intent);
    tabHost.addTab(spec);

    // 各タブでも同様の処理をする
    intent = new Intent().setClass(this, AlbumsActivity.class);
    spec = tabHost.newTabSpec("albums").setIndicator("Albums",
                      res.getDrawable(R.drawable.ic_tab_albums))
                  .setContent(intent);
    tabHost.addTab(spec);

    intent = new Intent().setClass(this, SongsActivity.class);
    spec = tabHost.newTabSpec("songs").setIndicator("Songs",
                      res.getDrawable(R.drawable.ic_tab_songs))
                  .setContent(intent);
    tabHost.addTab(spec);

    // 選択中のタブを 2番目(Songs) にセット
    tabHost.setCurrentTab(2);
}

artists、albums、songs で似たようなコードが重複しているのでちょっと長く見えます。

AndroidManifest.xml を編集

AndroidManifest.xml の <Application> の中身を以下のように書き換えます。

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".TabLayoutActivity"
                  android:label="@string/app_name"
                  android:theme="@android:style/Theme.NoTitleBar"
                  >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".ArtistsActivity" />
        <activity android:name=".AlbumsActivity" />
        <activity android:name=".SongsActivity" />
    </application>

最初のアクティビティに android:theme=”@android:style/Theme.NoTitleBar” の属性を追記したことと、ArtistsActivity、AlbumsActivity、SongsActivity のアクティビティを新たに追記しました。

android:theme=”@android:style/Theme.NoTitleBar” は見たままですが、メインのアクティビティのタイトルバーを非表示に指定しています。

アクティビティは AndroidManifest で <activity> によって追加されていないと、参照することができないので、新しく作った、ArtistsActivity、AlbumsActivity、SongsActivity のアクティビティを追記しています。

実行

ここまできたら、アプリケーションを実行してみましょう。

アイコンファイルを使いまわしているので、三つとも同じ画像になってしまいましたが、完成です。

正直、Intent とか TabSpec とか唐突にでてきたので、ほとんど理解できてません。急にハードル上がった気が…。

一応やってることはボンヤリわかるし、この形が定石だと思うので、きちんとした理解は後回しにして、使う機会があったらスニペットとして利用することにします。

シェアする

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

フォローする