It’s now or never

IT系の技術ブログです。気になったこと、勉強したことを備忘録的にまとめて行きます。

【Android】ActionBarにタブコントロールを実装する

ActionBarには、フラグメントを切り替えるタブコントロールを実装することができます。
タブには、タイトル文字列やアイコン画像をセットすることが可能です。

TabListenerの実装

アクションバータブのイベントを制御するにはActionBar.TabListenerを実装する必要があります。

各abstractメソッドは、以下のとおりです。

メソッド 概要
onTabSelected() タブが選択された時に呼ばれる
onTabUnselected() タブが非選択になった時に呼ばれる
onTabReselected() 同じタブが再度選択された時に呼ばれる


実装メソッドには、イベントを受け取ったActionBar.TabインスタンスおよびFragmentTransactionインスタンスが引数として渡されます。
コンストラクタにてあらかじめ対象のフラグメントを渡しておき、 上記の実装メソッドでフラグメントの追加や削除を行います。

MyTabListener.java

public class MyTabListener implements ActionBar.TabListener {
    private Fragment mFragment;

    // 新規タブを作成する際にフラグメントインスタンスを一緒に渡す
    public MyTabListener(Fragment fragment) {
        mFragment = fragment;
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // タブが選択された時の処理
        // フラグメントを追加する
        ft.add(R.id.fragment_content, mFragment, null);
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        // タブが切り替えられた時の処理
        // フラグメントを削除する
        ft.remove(mFragment);
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
        // 同じタブを再度タップされた時の処理
        // do nothing
    }
}

注意事項

トランザクションの管理は、システムが代わりに呼び出しを行うため、 FragmentTransactionに対してcommit()を呼び出してはいけません。
自分で呼び出した場合は、例外が投げられる可能性があります。
また、トランザクションをバックスタックに追加することもできません。

ActionBarの実装

ActivityクラスにてgetActionBar()を使って取得したActionBarインスタンスに対して、 setNavigationMode(ActionBar.NAVIGATION_MODE_TABS)を設定することで、
ActionBarをタブ表示モードへ切り替えることができます。

final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

ActionBarに対してタブを追加するには、 actionBar.newTab()で取得したインスタンスaddTab()にて追加します。
この時、タブに対してタイトル及びアイコン画像をセットすることが可能です。
また、タブの切り替え制御を行うために、上記で作成したActionBar.TabListenerをセットします。

// フラグメントを生成してTabへセット
Fragment fragment1 = new Fragment1();
ActionBar.Tab tab1 = actionBar.newTab();
tab1.setText("タブタイトル1"); // タイトル文字列
tab1.setIcon(R.drawable.ic_launcher); // アイコン
tab1.setTabListener(new MyTabListener(fragment1)); // リスナー
actionBar.addTab(tab1);


これでActionBarに対してタブコントロールを実装することができました。

f:id:inon29:20140311214238p:plain


今回実装した、サンプルソースを記載します。

MainActivity.java

// APIレベル11以上のみ対応
@SuppressLint("NewApi")
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.setDisplayShowTitleEnabled(false);

        // フラグメントを生成してTabへセット
        Fragment fragment1 = new Fragment1();
        // 新しく生成したTabインスタンスには、タイトル文字列、アイコン、リスナーをセットすることができる
        ActionBar.Tab tab1 = actionBar.newTab();
        tab1.setText("タブタイトル1");
        tab1.setIcon(R.drawable.ic_launcher);
        tab1.setTabListener(new MyTabListener(fragment1));
        actionBar.addTab(tab1);

        Fragment fragmet2 = new Fragment2();
        actionBar.addTab(actionBar.newTab().setText("タブタイトル2")
                .setTabListener(new MyTabListener(fragmet2)));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
}

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

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

tab1_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TextView 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="フラグメント1"/>

</LinearLayout>

tab2_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <TextView 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="フラグメント2"/>

</LinearLayout>

参考

http://www.techdoctranslator.com/android/guide/ui/actionbar