Help us understand the problem. What is going on with this article?

AndroidのToolBar(新しいActionBar)メモ

More than 3 years have passed since last update.

ToolBarとは?

Android 5.0 (Lollipop)と同時に追加されたActionBarの代替となるコンポーネント。
従来のActionBarに比べて、

  • カスタマイズしやすい
  • 他のビューのスクロールに合わせてアニメーションしやすい

などのメリットがあるらしい。
Android 5.0でマテリアルデザインが導入されたことでActionBar周りのUIガイドラインも微妙に変わっているようで、それに合わせてToolBarが追加された模様。

ちなみに、support library v7にも入ってるので、4.4以前の古いAndroidでもちゃんと使える。

基本的な使い方

Android 4.x時代のActionBarは、レイアウトXMLに明示的に書かないでActivityのthemeをTheme.AppCompat.Lightとかってしとけば勝手に表示されてた。
ToolBarは、これとは違って各自レイアウトXML内に書くスタイルの模様

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <!-- ここにToolBarを定義 -->
    <android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary">
    </android.support.v7.widget.Toolbar>

    <!-- 以下、その他のビュー(省略) -->

</RelativeLayout>

そして、ActivityのonCreateで、以下のようにアクションバーとしてセットする。こうしとくと、これまで使ってたアクションバーの機能(upナビゲーションとかメニューとか)がそのまま使える

public class MainActivity extends ActionBarActivity {

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

        // ツールバーをアクションバーとしてセット
        Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar);
        setSupportActionBar(toolbar);
    }
}

ちなみに、setSupportActionBarせずに、ただのビューとしてToolBarを使える。その場合はメニューが自動でinflateされないので、以下のようにプログラムでinflateできる。

toolbar.inflateMenu(R.menu.main);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                int id = menuItem.getItemId();
                if (id == R.id.action_settings) {
                    Toast.makeText(MainActivity.this, "settings clicked 2", Toast.LENGTH_SHORT).show();
                    return true;
                }
                return false;
            }
        });

基本はsetSupportActionBarをすることになると思うが、ToolBarに独自の動きをさせたい場合などは後者の使い方になるかも

ToolBarのデザインをカスタマイズ

styles.xmlを編集する。

setSupportActionBarを呼ぶ場合は従来のActionBarみたいによしななスタイルになるが、呼ばない場合は背景やテキスト色などtoolbarStyleに色々定義する必要あり。

iOS7みたいにcolorPrimaryDarkでステータスバーの色を変更できるみたいだけど、KitKatだと反映されなかったのでLollipop以降のみ反映されるのかも。

styles.xml
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

        <item name="colorPrimary">@android:color/white</item>
        <item name="colorPrimaryDark">@android:color/darker_gray</item>
        <item name="colorAccent">#ff0000</item>

        <!-- Toolbarのnavigation & overflow icon の色 -->
        <item name="colorControlNormal">@color/white</item>

        <!-- ActionModeを使うのに必要(後述) -->
        <item name="windowActionModeOverlay">true</item>

        <!-- Toolarのスタイル -->
        <item name="toolbarStyle">@style/MyApp.Toolbar</item>
    </style>

        <style name="MyApp.Toolbar" parent="Widget.AppCompat.Toolbar">
        <item name="android:background">@color/toolbar_bg</item>
        <item name="titleTextAppearance">@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse</item>
        <item name="subtitleTextAppearance">@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle.Inverse</item>
    </style>

</resources>

ToolBar内の要素

ツールバーの中には、左から順に以下の要素が入る

  1. ナビゲーションボタン
  2. ロゴ
  3. タイトルとサブタイトル
    • ロゴを使用する場合は使用しない方がいい
  4. カスタムビュー(複数可)
  5. メニュー

ナビゲーションボタン

ActionBarにあったHome/Upナビゲーション関連のメソッドが大方ToolBarには存在しないので、ToolBarを単体で使う場合(setSupportActionBarしない場合)は、ToolBar$setNavigationIconを代わりに使う。

    toolbar.setNavigationIcon(R.drawable.ic_launcher);
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, "Navigation click", Toast.LENGTH_SHORT).show();
            }
        });

setSupportActionBar(ToolBar)を呼ぶ場合は、普通のActionBarのUpナビゲーションを使える。

DetailActivity.java
public class DetailActivity extends ActionBarActivity {

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

        // ツールバーをアクションバーとして使う
        Toolbar toolbar = (Toolbar)findViewById(R.id.tool_bar);
        setSupportActionBar(toolbar);

        // UPナビゲーションを有効化する
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }


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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        // いつものUPナビゲーションの処理
        switch (id) {
            case android.R.id.home:
                NavUtils.navigateUpFromSameTask(this);
                return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

AndroidManifest.xmlで、親のActivityを指定するのもお忘れなく

AndroidManifest.xml
        <activity
            android:name=".DetailActivity"
            android:label="@string/title_activity_detail" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="com.exmaple.MasterActivity" />
        </activity>

ロゴ・タイトル

ロゴ、タイトル用のメソッドもある

toolbar.setLogo(R.drawable.ic_launcher);

toolbar.setTitle("This is title");

toolbar.setSubtitle("This is sub-title");

デザイン的には、

In modern Android UIs developers should lean more on a visually distinct color scheme for toolbars than on their application icon. The use of application icon plus title as a standard layout is discouraged on API 21 devices and newer.

とAPI referenceに書いてあるので、アイコン+テキストをバーの左に表示するUIは推奨されない。アイコンよりも色などでアプリの個性を出せとのこと。

ToolBarにカスタムビューを追加

レイアウトのXMLに以下のようにして子ビューを入れ子にすればOK

<android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary">

        <!-- ためしにスピナーを追加 -->
        <Spinner
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:entries="@array/spinner_values"
            android:id="@+id/spinner" />

</android.support.v7.widget.Toolbar>

メニュー

setSupportActionBarを呼ぶ場合

setSupportActionBarを呼んだ場合は、従来のActionBarと一緒なので省略
SearchViewなどのActionViewもそのまま使える

setSupportActionBarを呼ばない場合

setSupportActionBarを呼ばない場合は、以下のようなコードでメニューのインフレート、クリックアクションのハンドリングができる

// インフレート
toolbar.inflateMenu(R.menu.hoge);
// リスナーの登録
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
    @Override
    public boolean onMenuItemClick(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.foo:
                // do foo
                return true;
        }
        return true;
    }
});

ActionModeは?

(ActionMode = Gmailアプリでメールを長押しした時にアクションバーの色が変わるアレ)

ActionModeも使えるっぽい。
ただし、styles.xmlに

<item name="windowActionModeOverlay">true</item>

を追加しないとToolBarとActionBarが二重に表示されるので注意

タブ

ICS以降でよく使われていたActionBarのタブ関連APIが軒並み非推奨になってる

代替案として、

などがあるみたい

タブを非推奨にするなら、SlidingTabsBasicをSupport Libraryに入れといて欲しい。。。

(追記)
TabLayoutがdesign libraryに追加されたので多分これを使うのが正しい
http://developer.android.com/intl/ja/reference/android/support/design/widget/TabLayout.html

ドロワー

マテリアルデザインのガイドラインでは、「ドロワーはアクションバーの上にかぶる」のが正しいとされているので、DrawerLayoutの中にToolbarを置くことになる。

参考: http://www.riaxdnp.jp/?p=6965

ツールバーに影を付けたい

昔のActionBarは勝手にバーの下部に影が出てたけど、Toolbarはそのままだと影が全く出ない。で、試した結果これがよさそう。

    <android.support.v7.widget.Toolbar
        android:id="@+id/tool_bar"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:elevation="4dp"
        android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
        android:minHeight="?attr/actionBarSize"
        android:background="?attr/colorPrimary">
    </android.support.v7.widget.Toolbar>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:foreground="?android:windowContentOverlay"
        android:layout_below="@+id/tool_bar">
    </FrameLayout> 

Toolbatのandroid:elevation="4dp"は、Lollipop移行でしか影が出ないので、
Pre-Lollipop用に、コンテンツ部分をFrameLayoutにまとめてandroid:foreground="?android:windowContentOverlay"を指定してあげる。

参考

大体このへんの記事のまとめです

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした