タブを使ったレイアウト ~ TabHost と TabWidget
もっともわかりやすい UI と評判の(本当か?)、タブ形式のレイアウトについて実装方法を記載します。
タブ形式はご存知のとおり、上側あるいは側面に内容を示すタブが表示され、それを選択(タップ)するとそのタブに関連した内容が表示されるというものです。
タブ形式のレイアウトは TabHost と TabWidget を用いて実装出来ます。
スマートフォンのアプリケーションには、タブの部分の領域がスペース的にもったいないようにも思えますが、もしかしたらタブレットではより多く利用されていくかもしれません。
ここで作るものの出来上がりは次のとおりです。
真ん中のタブをタップすると・・・
となります。
タブの実装方法
タブを選択した時に、それぞれ別のアクティビティがフレームレイアウト (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);
}
}