タブを用いた画面を作成する / Getting Started


Androidでは、下図に示すように、タブを利用して画面に表示する内容を切り替えることができます。

図:タブを切り替える(firstTab→secondTab)

Androidではタブを簡単に使用するための仕組みとして、TabActivityが用意されています。
今回はこのTabActivityを利用して、タブを利用した画面を作成します。

ポイントは以下の点です。

  • タブを利用する際に使用するレイアウトファイルの構成
  • タブを使用する際に必要な主要クラス(TabHostTabSpec)
  • タブに表示する内容(View)の動的な生成

以上の3点に重点を起きながら、解説を進めていきます。

それでは続きをどうぞ

レイアウトの構成

まずはタブを利用するためのレイアウトファイルの構成について解説します。
タブを利用する際のレイアウト構成(アウトライン)は以下のようになります。
main.xml

図:タブレイアウトのアウトライン

レイアウト作成時には、以下の点に注意しなければなりません。

  • TabHostはレイアウト構造のrootに置く
  • TabWidgetのidは、 android:id=”@android:id/tabs”を指定する
  • FrameLayoutのidは、android:id=”@android:id/tabcontent”を指定する
  • TabWidgetとFrameLayoutをくくっているLinearlayoutは、android:orientation=”vertical”を指定する

以下は実際に作成したレイアウトファイル(main.xml)の内容になります。
main.xml


1行目、TabHostタグがレイアウトのrootになっていることがわかります。
6行目で、タブウィジェット<TabWidget>を定義しています。
FrameLayout内で、各タブが選択された際に表示したいViewをレイアウトファイルにてあらかじめ(静的に)定義しています(10行目〜19行目)。
TabWidgetとFrameLayoutを縦に並べるために、LinearLayoutのOrientationにVerticalを指定します(4行目)。
タブ選択時に表示する内容は、このようにあらかじめレイアウトファイル内で定義することも可能ですが、タブ選択時に動的に生成することも可能です(後ほど解説)。
なお、FrameLayoutとTabWidgetは同じ階層であることに注意してください。以下はレイアウトファイルの構成のイメージです。

図:レイアウトファイルの画面イメージ

TabActivityの定義

TabActivityを利用する上で重要なクラスは、TabHostクラスとTabSpecクラスです。
イメージとしては、TabHostはタブを用いた画面全体の設定を、TabSpecは各タブ毎の設定を行うようなイメージです。

図:TabHost、TabSpecのイメージ図

TabHostの生成と、TabHostへのタブ(TabSpec)の追加を行うソースコードは以下のようになります。
TabAct.java

public class TabAct extends TabActivity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //TabHostクラスのインスタンス生成
        TabHost tabHost = getTabHost();

        // TabHostからTabSpecの生成
        TabSpec firstTab = tabHost.newTabSpec("First");
        // タブ部分に表示するテキストおよびアイコンのセット
        firstTab.setIndicator("firstTab", getResources().getDrawable(android.R.drawable.ic_menu_agenda));
        // タブ選択時に表示したいViewのセット
        firstTab.setContent(R.id.first_content);
        // タブをTabHostに追加
        tabHost.addTab(firstTab);
                    :
               2つ目のタブ
                    :
        //最初にカーソルを当てたいタブを指定
        tabHost.setCurrentTabByTag("First");

    }

getTabHostはTabActivityで定義されているメソッドで、TabHostのインスタンスを取得します(8行目)。
TabHostのインスタンスから各タブを生成するには、TabHostクラスのnewTabSpec()メソッドを利用してTabSpecクラスのインスタンスを取得します(11行目)。引数には、生成するタブを識別するためのタグとして、タブに固有の任意の文字列を指定します。
TabSpecのインスタンスを生成したら、TabSpecクラスのsetIndicator()メソッドを使用してタブの部分に表示するテキストとアイコンを指定します(テキストのみ表示したい場合は第2引数は指定しなくて構いません)(13行目)。
タブ選択時に表示したい内容(View)は、TabSpecクラスのsetContent()メソッドに、main.xmlファイルにて定義したViewのidを指定するようにします(15行目)。
最後にaddTab()メソッドを用いて、生成したTabSpecをTabHostに追加します(17行目)。
もう一つタブを追加したい場合は、1行目〜17行目を繰り返します。

ちなみに、TabHostクラスのsetCurrentTableByTag()メソッドでは、引数に指定したタグ(newTagSpecの引数に指定した値)を持つタブを、初期表示時に選択された状態にします。

実行結果は以下のようになります。

動的にタブを追加する

先ほどの例では、あらかじめレイアウトファイル(main.xml)にて定義したViewのIDを、 setContent()メソッドの引数に指定することで、タブの内容として表示させました。
次は、タブを選択された際に、タブ内に表示するViewを(動的に)生成し、3つ目のタブとして表示させます。

動的にタブを生成するには、タブが選択された際のイベントを取得して処理を記述できるメソッドが必要です。
イベントを取得するには、TabActivityを継承したTabActクラスにTabHost.TabContentFactoryをimplementsし、createTabContentクラスを使用します
createTabContentは、タブ画面生成後、指定のタブが選択されたときに呼び出されます。
今回は、タブが選択されたときの時刻を、三つ目のタブに表示してみます。

TabAct.java

public class TabAct extends TabActivity implements TabHost.TabContentFactory {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
                (...省略...)
        //3つ目のタブを生成
        TabSpec thirdTab = tabHost.newTabSpec("Third");
        thirdTab.setIndicator("thirdTab", getResources().getDrawable(android.R.drawable.ic_menu_add));
        thirdTab.setContent(this);
        tabHost.addTab(thirdTab);
                (...省略...)
    }
	@Override
	public View createTabContent(String tag) {
		Time time = new Time("Asia/Tokyo");
		time.setToNow();
		String date = time.year + "年" + (time.month+1) + "月" + time.monthDay + "日" + time.hour + "時" + time.minute + "分" + time.second + "秒";
		TextView textView = new TextView(this);
		textView.setText(date);
		return textView;
	}
}

タブの生成方法は一つ目のタブ生成時とほとんど変わりありませんが、10行目のsetContent()メソッドのところでthisを指定します。
あとは、タブ選択時にcreateTabContent()クラスが呼ばれ、createTabContent()クラス内で生成されたViewが返されてタブの内容として表示されます。

なお、Timeクラスはandroid.text.format.Timeパッケージに定義されたクラスで、地域を指定することで、その地域の現在時刻を取得することができるクラスです。

実行結果は以下になります。選択時の時刻を取得して表示しています。

図:三つ目のタブ選択時画像

注意しなければならないのは、 createTabContentクラスはタブが選択される度に呼ばれるのではなく、タブが生成されてから一回目の選択時にのみ呼ばれるという点です。

まとめ

長くなってしまったのでおさらいです。今回は、以下の三節でそれぞれ次のポイントを解説しました。
レイアウトの定義
TabActivityで使用するレイアウトの定義について解説しました。レイアウトの構造と注意しなければならない点を4つ上げました。
TabActivityの定義
→Activityの変わりに、TabActivityを用いて画面を作成しました。TabHostTabSpecという二つの主要クラスの解説と、レイアウトファイルにて静的に定義したタブの内容を表示する方法を解説しました。
動的にタブを追加する
→タブが選択された時点で動的にタブに表示する内容(View)を生成して表示する方法を解説しました。

少し長かったですが、ソースファイルも、レイアウトファイルとjavaファイルの二つだけで、内容はそれほど複雑ではありません。

以上がタブの基本的な利用方法です。