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以降のみ反映されるのかも。
<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内の要素
ツールバーの中には、左から順に以下の要素が入る
- ナビゲーションボタン
- ロゴ
- タイトルとサブタイトル
- ロゴを使用する場合は使用しない方がいい
- カスタムビュー(複数可)
- メニュー
ナビゲーションボタン
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ナビゲーションを使える。
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を指定するのもお忘れなく
<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が軒並み非推奨になってる
代替案として、
- PagerTabStripを追加する
- 見た目がいわゆるタブっぽくないので微妙かも
- Google公式サンプルのSlidingTabsBasicを使う
- 見た目がそれっぽい。タブのカーソル(ハイライト部分)がViewPagerに合わせて一緒に動くなどすぐれもの
- http://developer.android.com/intl/ja/samples/SlidingTabsBasic/index.html
- TabHostを使う
などがあるみたい
タブを非推奨にするなら、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"を指定してあげる。
参考
大体このへんの記事のまとめです