Fragmentによるタブのレイアウト


[Fragmentによるタブ作成 関連記事]

前回はAndroid1.6以降のSDKでもFragment が使えるようにサポートライブラリについてみた。今回は、ほげほげ(仮)さんのサイトを参考にまずはUI作成の作業をメモっていく。

UI構成


tab_fragment_009
上端にタブがあって、タブを選択するごとにコンテンツ部分の内容が切り替わるという単純なUIにした。このコンテンツ部分が今回はFragmentになる。
tab_fragment_010
Fragmentなので各コンテンツがそれぞれ独立したライフサイクルをもつ。
※詳しくは 1.1 フラグメント - ソフトウェア技術ドキュメントを勝手に翻訳 を参考に

レイアウトファイル


tab_fragment_012

タブ化された UI を作成するには、TabHostTabWidget を使用する必要がある。TabHost はレイアウトのルートノードである必要があり、ここにはタブを表示するための TabWidget とコンテンツを表示するための FrameLayout の両方が必要となる。TabWidgetFrameLayout 要素はそれぞれ tabstabcontent という ID を持つ。これらの名前は指定されている必要があり、そうすることで TabHost がそれぞれの参照をその名前で取得できるようになる。

  1. レイアウトルートはTabHost
  2. タブ表示用にTabWidget必要
  3. コンテンツ表示用にFrameLayout必要(※ダミーとなる)
  4. TabWidgetのIDは "tabs"  にする必要がある
  5. FrameLayoutの1つのIDは "tabcontent "にする必要がある
  6. Fragmentでのコンテンツ表示用にFrameLayoutを準備する

以上がレイアウトファイルの構成となる。
※詳しくは 2.5 タブレイアウト - ソフトウェア技術ドキュメントを勝手に翻訳 を参考に。

以下のようなコードで、ファイル名は "activity_tabhost.xml" にした。

    
<TabHost
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
         <TabWidget
            android:id="@android:id/tabs"
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="0"/>        
		 <!-- TabHostの仕様上必要 -->
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="0"/>
        <!-- 実際のコンテンツ領域(Fragment) -->
        <FrameLayout
            android:id="@+id/realtabcontent"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>
</TabHost>

Activity 作成


以下のようなコードにした。

  
package localhost.test_tab_fragment;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.widget.TabHost;
import android.widget.TabHost.TabContentFactory;
import android.widget.TabHost.TabSpec;

public class MainActivity extends FragmentActivity {

	// TabHost
    private TabHost mTabHost;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tabhost);

        mTabHost = (TabHost) findViewById(android.R.id.tabhost);
        mTabHost.setup();        

        /* Tab1 設定 */
        TabSpec tab1 = mTabHost.newTabSpec("tab1");
        tab1.setIndicator("TAB1");                  
        tab1.setContent(new DummyTabFactory(this)); 
        mTabHost.addTab(tab1);                      

        // Tab2 設定
        TabSpec tab2 = mTabHost.newTabSpec("tab2");
        tab2.setIndicator("TAB2");                  
        tab2.setContent(new DummyTabFactory(this)); 
        mTabHost.addTab(tab2);                      

        // Tab3 設定
        TabSpec tab3 = mTabHost.newTabSpec("tab3");
        tab3.setIndicator("TAB3");                  
        tab3.setContent(new DummyTabFactory(this)); 
        mTabHost.addTab(tab3);                          
    }
    /*
     * android:id/tabcontent のダミーコンテンツ
     */
    private static class DummyTabFactory implements TabContentFactory {

        /* Context */
        private final Context mContext;

        DummyTabFactory(Context context) {
            mContext = context;
        }

        @Override
        public View createTabContent(String tag) {
            View v = new View(mContext);
            return v;
        }
    }  
}

FragmentはAndroid SDK 3.0 からでないとサポートされていない。Android1.6以降のSDKでもFragment が使えるようにサポートライブラリ android-support-v4.jar を使うことにする。

※詳しくは Android1.6以上で Fragment 対応 / android-support-v4 を参考に

    
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity

API Level 10 (Android 2.3.3) 以前のActivityには Fragmentを操作するAPIが用意されていない。なのでActivity から Fragmentを操作する FragmentActivity を継承する必要がある。この FragmentActivity はサポートライブラリにしか含まれていない。

  
mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mTabHost.setup();

tab_fragment_013

findViewById() を使って TabHost を読み込むとき タブを追加する前に setup() を呼ぶ必要があるようだ。TabActivity での getTabHost() の後では必要ない処理なので注意点となる。

  
/* Tab1 設定 */
TabSpec tab1 = mTabHost.newTabSpec("tab1");
tab1.setIndicator("TAB1");                  
tab1.setContent(new DummyTabFactory(this)); 
mTabHost.addTab(tab1);                      

// Tab2 設定
TabSpec tab2 = mTabHost.newTabSpec("tab2");
tab2.setIndicator("TAB2");                  
tab2.setContent(new DummyTabFactory(this)); 
mTabHost.addTab(tab2);                      

// Tab3 設定
TabSpec tab3 = mTabHost.newTabSpec("tab3");
tab3.setIndicator("TAB3");                  
tab3.setContent(new DummyTabFactory(this)); 
mTabHost.addTab(tab3);

tab_fragment_015

レイアウトファイル "activity_tabhost.xml" ではタブを配置する領域を指定しただけなので、各タブは mTabHost.newTabSpec() で生成する。

tab_fragment_016
setIndicator() でタブにラベルを付ける。

setContent() ではタブが選択されたとき、そのタブに対応するコンテンツ処理を指定をする。TabHost の仕様上、コンテンツとしてIDが tabcontent の FrameLayout 要素を作っているが今回は使わない。必要ないので setContent() を 外してみたがエラーになった。 よってダミー処理を行うことにする。

addTab() では、タブを配置する領域に順番に生成されたタブを配置していく。

  
private static class DummyTabFactory implements TabContentFactory {

    /* Context */
    private final Context mContext;

    DummyTabFactory(Context context) {
        mContext = context;
    }

    @Override
    public View createTabContent(String tag) {
        View v = new View(mContext);
        return v;
    }
}

TabContentFactory インターフェースを実装すると、createTabContent() の戻り値の View がタブのコンテンツとして表示されるが今回はダミーなので特に何も処理していない。

これでとりあえずタブのUI部分は作成できた。まだタブを選択してコンテンツとなるFragment を切り替える処理はできていないが次回そこの部分をまとめたいと思う。

参考



[Fragmentによるタブ作成 関連記事]

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です