タブを使ったレイアウト ~ TabHost と TabWidget

もっともわかりやすい UI と評判の(本当か?)、タブ形式のレイアウトについて実装方法を記載します。

タブ形式はご存知のとおり、上側あるいは側面に内容を示すタブが表示され、それを選択(タップ)するとそのタブに関連した内容が表示されるというものです。

タブ形式のレイアウトは TabHost と TabWidget を用いて実装出来ます。

スマートフォンのアプリケーションには、タブの部分の領域がスペース的にもったいないようにも思えますが、もしかしたらタブレットではより多く利用されていくかもしれません。

ここで作るものの出来上がりは次のとおりです。

Android タブ

真ん中のタブをタップすると・・・

Android タブ

となります。

タブの実装方法

タブを選択した時に、それぞれ別のアクティビティがフレームレイアウト (Framelayout) の中にロードされるという内容のコードを記載します。

タブ毎のアクティビティ

今回はタブを三つ用意するつもりなので、アクティビティを三つ用意します。 ほぼ同じコードで繰り返しになるので、一個だけ記載します。これの Tab1 の部分を Tab2、Tab3 とするだけです。

package com.keicode.android.test;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class Tab1Activity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TextView view = new TextView(this);
    view.setText("Tab1");
    setContentView(view);
  }
}

Activity クラスを追加したら、 AndroidManifest.xml にも忘れずアクティビティのエントリを追加しておきます。

<?xml version="1.0" encoding="utf-8"?>
<manifest 
  ...
<application 
  android:icon="@drawable/icon" 
  android:label="@string/app_name">
  <activity android:name=".Tab1Activity"></activity>
  <activity android:name=".Tab2Activity"></activity>
  <activity android:name=".Tab3Activity"></activity>
  <activity android:name=".TabLayoutTest1">
    <intent-filter>
      <action android:name="android.intent.action.MAIN" />
      <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
  </activity>
</application>
</manifest>

アイコンの準備

タブに表示するアイコンを用意します。こんなやつです。

そして、 res/drawable に次のような XML を作ります。

<?xml version="1.0" encoding="utf-8"?>
<selector 
  xmlns:android="http://schemas.android.com/apk/res/android">
  <item 
    android:state_selected="true" 
    android:state_pressed="false" 
    android:drawable="@drawable/ic_tab_b_selected" />
  <item android:drawable="@drawable/ic_tab_b_unselected" />
</selector>

この辺は Android Asset Studio などを使うと自動的にやってくれます。

メインのレイアウト

メインのレイアウトで注意する点は、次の三つです。

  • ルート要素を TabHost とする
  • タブを含むウィジェット TabWidget の ID を tabs とする
  • タブのコンテンツを含むウィジェットの ID を tabcontent とする

ルートは TabHost となりますが、その中に Layout を含めるのでかなり自由にレイアウト可能ですね。

<?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 へのタブの追加

package com.keicode.android.test;

import android.app.TabActivity;
import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.widget.TabHost;

public class TabLayoutTest1 extends TabActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);    
    initTabs();
  }
  
  protected void initTabs(){
    
    Resources res = getResources();
      TabHost tabHost = getTabHost();
      TabHost.TabSpec spec;
      Intent intent;

      // Tab1
      intent = new Intent().setClass(this, Tab1Activity.class);
      spec = tabHost.newTabSpec("Tab1").setIndicator(
        "Tab1", res.getDrawable(R.drawable.ic_tab_p))
        .setContent(intent);
      tabHost.addTab(spec);
      
      // Tab2
      intent = new Intent().setClass(this, Tab2Activity.class);
      spec = tabHost.newTabSpec("Tab2").setIndicator(
        "Tab2" , res.getDrawable(R.drawable.ic_tab_c))
        .setContent(intent);
      tabHost.addTab(spec);
      
      // Tab3
      intent = new Intent().setClass(this, Tab3Activity.class);
      spec = tabHost.newTabSpec("Tab3").setIndicator(
        "Tab3", res.getDrawable(R.drawable.ic_tab_b))
        .setContent(intent);
      tabHost.addTab(spec);
      
      // Set Default Tab - zero based index
      tabHost.setCurrentTab(0);

  }

}

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Android 開発入門