読者です 読者をやめる 読者になる 読者になる

なるようになるかも

力は多くの場合、その人の思いを超えない。

今更AndroidのToolbarについて理解できたような気がするのでメモ。

気のせいかもしれません。

Toolbar

Toolbar は Action Bar を一般化させたもので、同様の機能を備えつつ、より高い柔軟性を提供します。通常の Action Bar と異なる点は、Toolbar は階層内のビューの 1 つであるということです。そのため、Toolbar のインスタンスは好きなところに配置することができ、他のビューと共存します。さらに、動きを与えたり、スクロール イベントに反応させたりもできます。Activity.setActionBar() をコールすることで、Toolbar を Activity の Action Bar として機能させることもできます。

Android アプリにマテリアル デザインを導入する - Google Developer Japan Blog

これがいまいち意味分からなかったので、原文読んでみました。

Toolbar

The toolbar is a generalization of the action bar pattern, providing similar functionality, but much more flexibility. Unlike the standard action bar, toolbar is a view in your hierarchy just like any other, so you can place instances wherever you like, interleave them with the rest of your views, animate, react to scroll events and so on. You can make the Toolbar act as your Activity’s Action Bar by calling Activity.setActionBar().

Implementing Material Design in Your Android app | Android Developers Blog

generalization of the action bar patternを「Action Bar を一般化」は全然意味違ってないです?「ActionBarパターンを普遍化させた」とかそんな感じのニュアンスに読めます。

toolbar is a view in your hierarchy just like any otherの部分、「他のビューと同じ階層にある」という点についてちょっと曖昧な書き方です。タイトルバー階層と、アプリが管理しているビュー階層が今までは別だったという前提が重要だと思いますので。

interleave them with the rest of your viewsを「他のビューと共存」は意訳なのか自分の訳が悪いのか微妙ですけど、「他のビューの余白に挿入」ってだけに読めます。

ActionBarはビュー階層に解放されました

この記事がとても参考になりました。

~2.XからAndroidにはActivity単位でラベルを表示できるタイトルバーの機能がありました。標準の見た目が残念すぎて、requestWindowFeature()でカスタマイズができるにも関わらず、大抵非表示にされていました。

3.Xでタイトルバーは多機能なActionBarに置き換えられました。しかし「2.Xでタイトルバー非表示にしつつ、3.X~ではActionBarを表示」と分岐を入れるのは好まれず、またActionBarをバックポートできるのはActionBarSherlockという非公式ライブラリしかなかったので、依然非表示にされたまま、ActionBarパターンの認知度はいまいちでした。

その状況が変わったのが2013年7月のAndroid Support Libraryrevision18によるActionBarのバックポートです。時期的には4.3(Jelly Beanの最後のマイナーアップデート)になって、ようやく公式でActionBarがバックポートされ、「iOSとは違うAndroidのパターンを見直そう」という機運が高まります。

そして5.0になるわけですが、ここにきてActionBarの定義が大きく変わったように思います。ロゴ画像ではなくカラーを利用したブランディング、ユーザーの管理するビュー階層への移動、ActionBar組み込みのナビゲーション機能(setNavigationMode())の廃止。

もはやActionBarはユーザービュー階層にあるのですから、その実装はユーザー次第であると考えると、NavigationModeが廃止されたのも理解できます。

しかしタイトルバーを非表示にしてToolbarを使うというのは、直感に反していて非常に微妙…。

2つあるToolbar

Toolbarは2つあります。android.widget.Toolbarandroid.v7.widget.Toolbarです。

Toolbar は AppCompat で完全にサポートされ、フレームワーク ウィジェットと同等の機能と API をもちます。

AppCompat v21 — Lollipop 搭載前のデバイスにマテリアル デザインを! - Google Developer Japan Blog

これ、前提としてandroid.widget.Toolbarがあって、その同等の機能がandroid.v7.widget.Toolbarで提供されている、という意味なのですね…。実際使ってみるまでは、v7ライブラリ専用の機能だとばかり。

両者は実機能としては違いがないのですが、本家がandroid:Theme.Materialテーマを前提としているのに対して、v7版はTheme.AppCompatテーマを前提としており、属性参照している値が異なります。

例によって、android:toolbarStyletoolbarStyleに分裂してるんでしょう。

Toolbarを使うときの注意

setSupportActionbar()を呼んで、ActionBarとして使うときは、以下のようにレイアウト指定します。

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

そうではなく、普通にViewGroupとして使うときには指定が変わります。

<android.support.v7.widget.Toolbar  
   android:layoutheight="wrapcontent"
   android:layoutwidth="matchparent"
   android:minHeight="?attr/actionBarSize"
   app:theme="@style/ThemeOverlay.AppCompat.ActionBar" /> 

画面に複数Toolbarを表示する場合に、それぞれに異なるスタイルを指定するためなのだと思いますが、トラップ感満載です。

ところで単純なViewGroupとしてみた場合、layout_gravityがレイアウトエディタ上でサジェストされなくて使い勝手が悪いんですけど、バグなんでしょうねー…。