ちょっと話題の記事

[Android Tips] Support Library に追加された ActionBarActivity を使ってみた

2013.07.30

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Support Library に ActionBar のサポートが追加

action_bar_activity01

7月24日に Android SDK 4.3 (APIレベル18) がリリースされ、ADT r18 がリリースされ、Support Library r18 がリリースされました。Support Library r18 では v7 で ActionBar が正式にサポートされました!
ということで新しく追加された ActionBarActivity を早速使ってみたのでメモしておきます。

Support Package v7 をインポートする

ActionBarActivity を使う上でまず必要なのが Support Package v7 です。このライブラリは Android 2.1 (APIレベル7) から使うことができます。Android Studio のプロジェクトであれば、build.gradledependencies に Support Package v7 のリポジトリを追加します。

build.gradle

dependencies {
    compile 'com.android.support:support-v4:13.0.+'
    compile 'com.android.support:appcompat-v7:18.0.+'
}

これで ActionBar, ActionBarActivity (ついでに ShareActionProvider) が使えるようになりました。

ActionBarActivity を使う

それでは ActionBarActivity を使ってみましょう。まずはテーマに Theme.AppCompatTheme.AppCompat.LightTheme.AppCompat.Light.DarkActionBar を設定します。その他のテーマはこちらを参照してください。

<style name="AppBaseTheme" parent="Theme.AppCompat.Light">
</style>

あとは Activity の親を ActionBarActivity に差し替えます。

public class MainActivity extends ActionBarActivity {

…

}

これで終わりです。めっちゃ簡単ですね! 2.3.3 で実行してみました。

action_bar_activity02

ActionBarActivity の ActionBar をいろいろカスタマイズする

せっかくなので色々試してみたいと思います。

タブを置いてみる

まずはタブを置いてみました。ActionBar の取得は getSupportActionBar() ですね。

ActionBar ab = getSupportActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ab.addTab(ab.newTab().setText("Tab1").setTabListener(mTabListener));
ab.addTab(ab.newTab().setText("Tab2").setTabListener(mTabListener));
ab.addTab(ab.newTab().setText("Tab3").setTabListener(mTabListener));

実行結果

action_bar_activity03

ドロップダウンリストを表示する

次にドロップダウンリスト形式のナビゲーションにしてみました。

ActionBar ab = getSupportActionBar();
ab.setDisplayShowTitleEnabled(false);
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);

SpinnerAdapter adapter = ArrayAdapter.createFromResource(
        this, R.array.list, android.R.layout.simple_list_item_1);
ab.setListNavigationCallbacks(adapter, new ActionBar.OnNavigationListener() {
    @Override
    public boolean onNavigationItemSelected(int i, long l) {
        return false;
    }
});

実行結果

action_bar_activity04

ちなみに Spinner が ICS のやつになってる!と思って見てみたら SpinnerICS というクラスを内部的に使っているみたいでした。このクラスは Internal なのでレイアウトでは使えませんでした。。

NavigationDrawer を使う

最近追加されたばかりの新しいナビゲーションパターンである NavigationDrawer を用いたナビゲーションも実装できます。まずは以下のようなレイアウトにします。

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- コンテンツ -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- Navigation Drawer -->
    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:background="#eee" />

</android.support.v4.widget.DrawerLayout>

次に Activity の実装です。公式のサンプルと同じように実装しましょう。

package jp.classmethod.android.sample.actionbar;

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends ActionBarActivity {

    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        ActionBar ab = getSupportActionBar();
        ab.setDisplayHomeAsUpEnabled(true);
        ab.setHomeButtonEnabled(true);

        // DrawerLayout
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

        // DrawerListを開く/閉じるトグルボタン
        mDrawerToggle = new ActionBarDrawerToggle(
                this,
                mDrawerLayout,
                R.drawable.ic_drawer,
                R.string.open,
                R.string.close
        );
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        // DrawerList
        mDrawerList = (ListView) findViewById(R.id.left_drawer);
        ArrayAdapter adapter = ArrayAdapter.createFromResource(
                this, R.array.list, android.R.layout.simple_list_item_1);
        mDrawerList.setAdapter(adapter);
        mDrawerList.setOnItemClickListener(mOnItemClickListener);
    }

    private AdapterView.OnItemClickListener mOnItemClickListener = new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            // DrawerLayoutを閉じる
            mDrawerLayout.closeDrawer(mDrawerList);
        }
    };

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // DrawerToggleの状態を同期する
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // DrawerToggleの状態を同期する
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    
}

ちなみにリソースに使っているアイコンも公式のサンプルからダウンロードできます。
これで実行すると以下のようになります!ActionBarSherlock だとそのままではアイコンが表示されなかったりしましたが、アニメーションも含めて正しく表示されました。

action_bar_activity05

ActionBarSherlock から移行したい場合

ActionBarSherlock から移行する方法は以下にまとめられています。

ActionBarActivity移行メモ | Qiita

ActionBarSherlock の API は標準 SDK の API に沿って実装されているので、テーマの定義と Activity と Fragment の親クラスの変更さえできればスムーズに移行可能できるようです。

まとめ

ActionBar が公式でサポートされたことにより、2系でも差し支えなく ActionBar を用いた実装ができるようになりました。今回は ActionBar の UI の実装を主に取り扱いましたがリファレンスを眺めてみると Up ナビゲーションのサポートも充実しているようでした(supportNavigateUpTo() やら onPrepareSupportNavigateUpTaskStack() やら)。
今後もバージョンアップしていくと思われるので、期待しましょう!
またデザインガイドラインをよく読んで、ユーザーが迷わないよう一貫したナビゲーションを提供するようにしましょう。

参考