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

新時代のToolBarへ

Android

はじめに

この記事は「Android Advent Calendar 2014」の13日目の記事です。
ホントは「今さら聞けない英単語の読み方」を書きたかったんですが、非常にレベルの高い記事ばかりで...

ToolBarとは

AndroidのToolBar(新しいActionBar)メモ - Qiita
こちらの記事にもあるようにActionBarの代替品という認識でいます。

例えば、ActionBarを真ん中に置きたいとき、

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

    <android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:minHeight="?attr/actionBarSize"
        android:background="@color/base_actionbar"
        android:id="@+id/main_tool_bar"/>

</RelativeLayout>

f:id:amyu_dev:20141210173654j:plain
ほら簡単!
Material DesignでActionBarもヌルヌル動かないといけない時代の必須アイテムですね!

今回のエントリではToolBarのソースをざっくり眺めて必要そうな情報を書き出してみました。
基本的にpublicで@hideではないメソッドを網羅してるはずです!

popupTheme

f:id:amyu_dev:20141210174332p:plain
このようにビロ~ンって出てくるpopupItemのthemeを結構簡単に変えることが出来ます。

style

<style name="PopupMenu" parent="Base.ThemeOverlay.AppCompat">
    <item name="android:background">@color/base_actionbar</item>
    <!-- <color name="base_actionbar">#e51c23</color> -->
</style>

xmlで指定するとき

<android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:minHeight="?attr/actionBarSize"
        android:background="@color/base_actionbar"
        app:popupTheme="@style/PopupMenu"
        android:id="@+id/tool_bar"/>

コードで指定するとき

Toolbar toolbar = (Toolbar) findViewById(R.id.main_tool_bar);
toolbar.setTitle("Action Bar");
toolbar.setPopupTheme(R.style.PopupMenu); 
//inflateMenuでViewの更新が入ってるっぽいのでinflateMenuより前で
toolbar.inflateMenu(R.menu.menu_main);

みたいな感じで指定すると、
f:id:amyu_dev:20141210180114p:plain
おぉ、すごい。
こんな感じで中の文字の色やその他いろいろを変えられます。

Logo

toolbar.setLogo(R.drawable.ic_launcher);

f:id:amyu_dev:20141210181049p:plain
ちょっとダサい感が否めない...

TitleとSubTitle

通常のTitleとSubTitleの表示はこんな感じ

toolbar.setTitle("Action Bar");
toolbar.setSubtitle("Sub Title");

f:id:amyu_dev:20141210182720p:plain

TitleやSubTitleにstyleを適用させて上げると

<style name="TextStyle">
    <item name="android:textColor">#00ff00</item>
    <item name="android:textStyle">bold</item>
</style>

toolbar.setSubtitleTextAppearance(getApplicationContext(),R.style.TextStyle);

f:id:amyu_dev:20141210183450p:plain

その他、setSubtitleTextColorsetTitleTextColorで色は簡単に変更することが出来ます。

NavigationIcon

NavigationIconの簡単なやつ

toolbar.setNavigationIcon(R.drawable.ic_launcher);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("log", "hogehoge");
    }
});

f:id:amyu_dev:20141210184136p:plain

Menu

Menuのinflate、ClickListener

toolbar.inflateMenu(R.menu.menu_main);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
    @Override
    public boolean onMenuItemClick(MenuItem menuItem) {
        return false;
    }
});

ContentInsetsAbsoluteとContentInsetsRelative

ToolBarタグのなかにViewを追加することが出来るのは知っていると思います。
例えばこんなレイアウトにした場合

<android.support.v7.widget.Toolbar
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:minHeight="?attr/actionBarSize"
    android:background="@color/base_actionbar"
    android:id="@+id/main_tool_bar">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:textSize="30sp"
        android:background="@android:color/white"
        android:textColor="@android:color/black"
        android:gravity="center"
        android:text="hogeeeeee"/>

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

f:id:amyu_dev:20141210190232p:plain
デフォルトのToolBarではこのように左が空いてる状態になります。
レイアウトを見る限りでは、内部にあるTextViewのwidthはmatchにしているので、画面横いっぱいになることを想定しています。
ところが左に微妙なマージンが発生しています。

これの原因が
ToolBar#mContentInsetsの初期値です。

final int contentInsetStart = a.getDimensionPixelOffset(R.styleable.Toolbar_contentInsetStart,
                        RtlSpacingHelper.UNDEFINED);
mContentInsets.setRelative(contentInsetStart, contentInsetEnd);

R.styleable.Toolbar_contentInsetStartの値が16dpになっています。

そのため、きっちり左上にスタートにしたい場合は

toolbar.setContentInsetsRelative(0,画面横のサイズ);

または

<android.support.v7.widget.Toolbar
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:minHeight="?attr/actionBarSize"
    android:background="@color/base_actionbar"
    app:contentInsetStart="0dp"
    android:id="@+id/main_tool_bar">
    <!-- app:contentInsetStart="0dp"これが大事 -->

    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:textSize="30sp"
        android:background="@android:color/white"
        android:textColor="@android:color/black"
        android:gravity="center"
        android:text="hogeeeeee"/>

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

にしてあげると
f:id:amyu_dev:20141210192039p:plain
このようにきっちり左上スタートになります。


今回のこの16dpというマージン、これMaterial Designのためなんですね。
Metrics & keylines - Layout - Google design guidelines
自分で16dpあけるとかしたほうが個人的にわかりやすいような気もするので、どっちがいいとは言えない感じ。

最後に

最初はタダのActionBarのラッパかなって思ってたんですけど、なんかいい感じな気がしてきました。
新規のプロジェクトからはToolBarを使っていきたいな!

あ、Twitterもよろしくお願いします...!


ではではー