アクションバーのタブ・ナビゲーション

以前はタブ形式のナビゲーションは TabHost と TabWidget を用いて実装されました。

タブホストとタブウィジェットを用いた実装については、タブを使ったレイアウト ~ TabHost と TabWidget をみてください。

しかしながら、アクションバーが導入されてからは、アクションバーのタブナビゲーションを利用することが推奨されています。

アクションバーのタブナビゲーションを利用することによって、タブナビゲーションに十分な幅が無い場合、自動的にタブが非表示になり、 アクションアイテム(ボタン)として表示されるようになるなど、より多くのスクリーンサイズに対応可能となります。

このため新しいアプリケーションでは、アクションバーを活用すべきです。

この資料ではアクションバーの "タブナビゲーションモード" の基本的な利用方法について説明します。

アクションバーのタブナビゲーション

アクションバーのタブ・ナビゲーションを利用すると、次のような UI となります。

ここではタブ "TAB 1" に "Fragment 1" と、タブ "TAB 2" に "Fragment 2" という文字を表示しています。

アンドロイドのアクションバーでのタブナビゲーション

アンドロイドのアクションバーでのタブナビゲーション

TabHost と TabWidget を利用した実装では、土台となるアクティビティが TabActivity から派生したクラスとなり、そこで取得できる TabHost に対して、Tab 1, Tab 2 となるアクティビティを追加しました。

アクションバーの実装では、アクションバーのナビゲーションモードを ActionBar.NAVIGATION_MODE_TABS として、 アクションバーにタブを追加します。タブの中身はフラグメントとします。

#フラグメントについては「フラグメント」をみてください。

従って、ここではタブを二個作るので、メインアクティビティとフラグメント2個を実装します。

レイアウトファイル

レイアウトは次の通り。次を res/layout/activity_main.xml とします。

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

次の内容を res/layout/fragment1.xml とします。単に TextView を使って文字を書いているだけです。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#ffffff">
  <TextView 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="30sp"
    android:textColor="#000000"
    android:text="Fragment 1"/>
</LinearLayout>

次の内容を res/layout/fragment2.xml とします。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#ffffff">
  <TextView 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="30sp"
    android:textColor="#000000"
    android:text="Fragment 2"/>
</LinearLayout>

タブの中身となるフラグメント

タブの中身となるフラグメント 1 (Fragment1) とフラグメント 2 (Fragment2) はそれぞれ次の通りです。

どちらもビューをレイアウトファイルから作成しているだけです。

package com.example.actionbartest1;

import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment1 extends Fragment {
  
  @Override
  public View onCreateView(
    LayoutInflater inflater,
    ViewGroup container,
    Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment1, container, false);
  }
  
}

Fragment2 は fragment2.xml を読み込みます。

package com.example.actionbartest1;

import android.os.Bundle;
import android.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment2 extends Fragment {

  @Override
  public View onCreateView(
    LayoutInflater inflater,
    ViewGroup container,
    Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment2, container, false);
  }

}

ウィジェットの状態の保存、元に戻すなどの操作は onSaveInstanceState とか onCreateView を使って行いますが、 これについては別の記事で書きたいと思います。

アクションバーとタブリスナーの設定

さて、やっとメインアクティビティの作成です。

ポイントは次の通りです。

  • onCreate でタブのナビゲーションモードを設定。(ActionBar の setNavigationMode メソッドを呼ぶ)
  • タブリスナー (TabListener) を作成
package com.example.actionbartest1;

import android.app.ActionBar;
import android.app.Activity;
import android.app.FragmentTransaction;
import android.app.ActionBar.Tab;
import android.app.ActionBar.TabListener;
import android.os.Bundle;
import android.app.Fragment;

public class MainActivity extends Activity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    
    final ActionBar actionBar = getActionBar();
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    actionBar.addTab(actionBar
      .newTab()
      .setText("TAB 1")
      .setTabListener(
        new MainTabListener<Fragment1>(
          this,
          "f1",
          Fragment1.class
        )
      )
    );
    actionBar.addTab(actionBar
      .newTab()
      .setText("TAB 2")
      .setTabListener(
        new MainTabListener<Fragment2>(
          this,
          "f2",
          Fragment2.class
        )
      )
    );
    }
    
  public static class MainTabListener<T extends Fragment> 
    implements TabListener {
    
    private Fragment fragment;
    private final Activity activity;
    private final String tag;
    private final Class<T> cls;
    
    public MainTabListener(
      Activity activity, String tag, Class<T> cls){
      this.activity = activity;
      this.tag = tag;
      this.cls = cls;
    }
      
    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
      if(fragment == null){
        fragment = Fragment.instantiate(activity, cls.getName());
        ft.add(android.R.id.content, fragment, tag);
      }
      else{
        ft.attach(fragment);
      }      
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
      if(fragment != null){
        ft.detach(fragment);
      }      
    }
    }
}

タブリスナーではタブの選択時、非選択時等の動作を定義します。

ここでフラグメントをインスタンス化して設定しています。

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

© 2024 Android 開発入門