2012年9月27日木曜日

Android TabActivityとTabHostを使用してTab画面を表示する

2012/11/19 追記
TabHostを使用する方法はAndroid 3.0 以降は非推奨となりました。
TabHostを使用せずにタブ画面を表示する方法はコチラ
Android ActionBarとFragmentを使用してTab画面を表示する(Android 4.0以上)
Android ActionBarとFragmentを使用してTab画面を表示する(Android 2.x)



むかし2年程前にタブメニューについて調べたんです。コレ→「Android タブ画面を表示する
今回タブを使おうと思って昔の記事を読んでみたんですが・・・全然わかんないわぁ(;´д`)
自分で読んでも何を書いてるのかわかんないのに、二人の人が役にたったとリアクションしてくれてます。ゴメンナサイ

結局、私の役にはたたなかったので、ほかの人のブログを参考にしました。
自分の調べた事をメモるブログなのに意味ないしっ(>_<)

気を取り直して、再度調べた事をまとめておきます。

タブメニューを作成するにはTabHostウィジェットを使用します。
ActivityにTabHostを配置し、ActivityのonCreate()でTabHostにタブを追加します。
各タブをクリックしたときに表示するコンテンツですが、以下の3通りがあるようです。
  1. TabHostを配置したアクティビティに定義したViewを表示する。
  2. 他のアクティビティを表示する
  3. layoutファイルに定義したViewを表示する

TabHostを配置したアクティビティに定義したViewを表示する

ActivityにTabHostを配置します。

アウトラインを見ると以下のようになっていると思います。
TabHost(id/tabhost)
 |--LinearLayout
    |--TabWidget(id/tabs)
      |--FrameLayout(id/tabcontent)
        |--LinearLayout(id/tabs1)
        |--LinearLayout(id/tabs2)
        |--LinearLayout(id/tabs3)

注意点は以下の3点です。
  • TabHostはidがtabhostであること。
  • TabWidgetはidがtabsであること。
  • FrameLayoutはidがtabcontentであること。

3つのLinearLayout(idがtab1,tab2,tab3)が各タブをクリックしたときに表示されるコンテンツになります。
タブを4つにしたければLinearLayoutをもう一つ追加します。

それでは各LinearLayoutに適当にウイジェットを配置します。
何か方法があるのかもしれませんが、2つめ以降のLinearLayoutをGraphicalLayoutでデザイン作成できないのが不便です。
アウトラインに追加し、XMLを編集していくしかないのですかね(´д`)

今回は各LinearLayoutにTextViewを1つずつ配置しました。

activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TabHost
        android:id="@android:id/tabhost"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" >
            </TabWidget>

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="match_parent"
                android:layout_height="match_parent" >

                <LinearLayout
                    android:id="@+id/tab1"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" >

                    <TextView
                        android:id="@+id/textView1"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Tabページ1" />

                </LinearLayout>

                <LinearLayout
                    android:id="@+id/tab2"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" >

                    <TextView
                        android:id="@+id/textView2"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Tabページ2" />

                </LinearLayout>

                <LinearLayout
                    android:id="@+id/tab3"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" >

                    <TextView
                        android:id="@+id/textView3"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Tabページ3" />

                </LinearLayout>

            </FrameLayout>
        </LinearLayout>
    </TabHost>

</RelativeLayout>

タブ部分に表示するテキストをres/values/strings.xmlに定義します。
<resources>
    :
    :
    <string name="tab1">ページ1</string>
    <string name="tab2">ページ2</string>
    <string name="tab3">ページ3</string>
</resources>

ActivityはTabActivityを継承して作成し、onCreate()でTabHostに各タブを追加していきます。
TabSpec#setIndicator()でタブ部分の文字を指定します。
TabSpec#setContent()でタブをクリックした時に表示するViewのidを指定します。
ここではactivity_main.xmlにある3つのLinearLayoutのidです。

MainActivity.java
public class MainActivity extends TabActivity {
        
    private static final String TAB[] = {"tab1", "tab2","tab3" };   
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //TabHostオブジェクト取得   
        TabHost tabhost = getTabHost();
        //Tab1設定   
        TabSpec tab1 = tabhost.newTabSpec(TAB[0]);   
        tab1.setIndicator(this.getResources().getString(R.string.tab1));       
        tab1.setContent(R.id.tab1);
        tabhost.addTab(tab1);       
        //Tab2設定   
        TabSpec tab2 = tabhost.newTabSpec(TAB[1]);   
        tab2.setIndicator(this.getResources().getString(R.string.tab2));      
        tab2.setContent(R.id.tab2);
        tabhost.addTab(tab2);   
        //Tab3設定   
        TabSpec tab3 = tabhost.newTabSpec(TAB[2]);   
        tab3.setIndicator(this.getResources().getString(R.string.tab3));      
        tab3.setContent(R.id.tab3);
        tabhost.addTab(tab3);       
        //初期表示するタブ   
        tabhost.setCurrentTab(0);  
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    } 

}

他のアクティビティを表示する

次はタブをクリックした時に表示するコンテンツにActivityを指定する方法です。

まずTabHostを配置したメインとなるアクティビティを1つ作成します。
そしてタブをクリックした時に表示するアクティビティをタブの数だけ作成します。

つまりタブが3つある画面であれば4つのアクティビティを作成することになります。

各タブのコンテンツとなるアクティビティ「Tab1Activity.java」、「Tab2Activity.java」、「Tab3Activity.java」を作成します。
各アクティビティには、それぞれの違いがわかるように適当にウィジェットを配置しておきます。

次にメインとなるActivityを作成します。
こちらは「TabHostを配置したアクティビティに定義したViewを表示する」で作成したMainActivity.javaとほぼ同じです。
違いは、TabSpec#setContent()でアクティビティを指定します。

MainActivity.java
public class MainActivity extends TabActivity {
        
    private static final String TAB[] = {"tab1", "tab2","tab3" };   
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //TabHostオブジェクト取得   
        TabHost tabhost = getTabHost();
        //Tab1設定   
        TabSpec tab1 = tabhost.newTabSpec(TAB[0]);   
        tab1.setIndicator(this.getResources().getString(R.string.tab1));       
        tab1.setContent(new Intent().setClass(this, Tab1Activity.class));
        tabhost.addTab(tab1);       
        //Tab2設定   
        TabSpec tab2 = tabhost.newTabSpec(TAB[1]);   
        tab2.setIndicator(this.getResources().getString(R.string.tab2));      
        tab2.setContent(new Intent().setClass(this, Tab2Activity.class));
        tabhost.addTab(tab2);   
        //Tab3設定   
        TabSpec tab3 = tabhost.newTabSpec(TAB[2]);   
        tab3.setIndicator(this.getResources().getString(R.string.tab3));      
        tab3.setContent(new Intent().setClass(this, Tab3Activity.class));
        tabhost.addTab(tab3);       
        //初期表示するタブ
        tabhost.setCurrentTab(0);  
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    } 

}
この方法はアクティビティがいっぱいになるのがイヤだな・・・

layoutファイルに定義したViewを表示する

最後にTabをクリックした時に表示するコンテンツに、res/layoutに作成したファイルを表示する方法です。
これが一番よいのではと思っています。

res/layoutを右クリックし「新規」→「その他」→「Android XML レイアウト・ファイル」を選択し
「tab1.xml」、「tab2.xml」、「tab3.xml」を作成します。

ルート要素はLinearLayoutにし、それぞれの違いがわかるように適当にウィジェットを配置しておきます。

次にメインとなるActivityを作成します。
こちらは「TabHostを配置したアクティビティに定義したViewを表示する」で作成したMainActivity.javaとほぼ同じです。
違いは、TabSpec#setContent()でTabContentFactoryインターフェースを実装したクラスを指定します。
TabContentFactoryのcreateTabContent()メソッドで先ほど作成したレイアウトファイルを返すようにします。
MainActivity.java
public class MainActivity extends TabActivity {
        
    private static final String TAB[] = {"tab1", "tab2","tab3" };   
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //タブに表示するViewをlayoutより取得する
        LayoutInflater layout = LayoutInflater.from(MainActivity.this); 
        final View viewTab1 = layout.inflate(R.layout.tab1, null);
        final View viewTab2 = layout.inflate(R.layout.tab2, null);
        final View viewTab3 = layout.inflate(R.layout.tab3, null);
        //TabHostオブジェクト取得   
        TabHost tabhost = getTabHost();
        //Tab1設定   
        TabSpec tab1 = tabhost.newTabSpec(TAB[0]);   
        tab1.setIndicator(this.getResources().getString(R.string.tab1));       
        tab1.setContent(new TabHost.TabContentFactory (){
            public View createTabContent(String tag) {return viewTab1;}
        });
        tabhost.addTab(tab1);       
        //Tab2設定   
        TabSpec tab2 = tabhost.newTabSpec(TAB[1]);   
        tab2.setIndicator(this.getResources().getString(R.string.tab2));      
        tab2.setContent(new TabHost.TabContentFactory (){
            public View createTabContent(String tag) {return viewTab2;}
        });
        tabhost.addTab(tab2);  
        //Tab3設定   
        TabSpec tab3 = tabhost.newTabSpec(TAB[2]);   
        tab3.setIndicator(this.getResources().getString(R.string.tab3));      
        tab3.setContent(new TabHost.TabContentFactory (){
            public View createTabContent(String tag) {return viewTab3;}
        });
        tabhost.addTab(tab3);  
        //初期表示するタブ   
        tabhost.setCurrentTab(0);  
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    } 

}


今回はちゃんとまとめられたと思うっ( *`ω´)

0 件のコメント: