Android

AndroidのToolBar(新しいActionBar)メモ

More than 1 year has 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"を指定してあげる。


参考

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