LoginSignup
10
10

More than 5 years have passed since last update.

Material Design の Flexible toolbar and card toolbar

Posted at

Structure - Layout - Material design guidelines にある Flexible toolbar and card toolbar を実装してみました。
このようなレイアウトです。
layout_structure_toolbars4.png

今回はタブレットを用意するのが面倒だったので、横画面の場合にこのレイアウトになるようにしてみます。

縦画面

まずは縦画面です。テンプレートで生成された Activity にメニューを一つ、TextView を一つ追加しました。
portrait.png

layout/app_bar_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.gsbina.cardtoolbar.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@android:drawable/ic_dialog_email"/>

</android.support.design.widget.CoordinatorLayout>
layout/content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minHeight="200dp"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.gsbina.cardtoolbar.MainActivity"
    tools:showIn="@layout/app_bar_main">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="@string/message"
        />
</RelativeLayout>

横画面

2つの Toolbar

Flexible toolbar and card toolbar というように、ハンバーガーアイコンを表示する Toolbar とタイトル、メニューを表示する Toolbar の 2 つに別れています。
前者を Toolbar、後者を Menubar と区別することにします。

Toolbar

Toolbar の高さを 2 倍にして、メニューの作成を行わないようにします。

layout-land/app_bar_main.xml
<android.support.design.widget.AppBarLayout
    android:id="@+id/app_bar_layout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <!-- @dimen/action_bar_size は ?attr/actionBarSize の 2 倍である 112dp -->
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/action_bar_size"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay"/>

</android.support.design.widget.AppBarLayout>
MainActivity.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
    if (!hasMenubar()) {
        getMenuInflater().inflate(R.menu.main, menu);
    }
    // Up ナビゲーションを考慮して true を返す
    return true;
}

private boolean hasMenubar() {
    return findViewById(R.id.menubar) != null;
}

Menubar

Menubar とコンテンツを含む CardView を追加します。

layout-land/app_bar_main.xml
<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <android.support.v7.widget.Toolbar
            android:id="@+id/menubar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/menu_bar_size"/>

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginTop="-1dp"
            android:background="?android:attr/listDivider"/>

        <include layout="@layout/content_main"/>

    </LinearLayout>

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

そして Menubar にタイトルを表示したり、メニューを作成します。

MainActivity.java
if (hasMenubar()) {
    Toolbar menubar = (Toolbar) findViewById(R.id.menubar);
    ActionBar actionBar = getSupportActionBar();
    if (actionBar != null) {
        // タイトルを表示する
        menubar.setTitle(actionBar.getTitle());
        actionBar.setTitle(null);

        // メニューを作成する
        menubar.inflateMenu(R.menu.main);
        menubar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                return onOptionsItemSelected(item);
            }
        });

        // 背景色と合うようにアイコンの色を変更する
        Drawable icon = menubar.getMenu().findItem(R.id.action_module).getIcon();
        icon.setTint(Color.GRAY);
        icon.setTintMode(PorterDuff.Mode.SRC_ATOP);
    }
}

Toolbar と Menubar の配置

Menubar が含まれる CardView は、Toolbar の半分の高さまで位置をずらして配置するために marginTop にマイナスの値を設定します。そして、ずらした CardView が被らないように Toolbar を含む AppBarLayout の elevation を 0 にします。

layout-land/app_bar_main.xml
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        app:elevation="0dp"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="@dimen/action_bar_size"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/app_bar_layout"
        android:layout_marginStart="@dimen/content_margin_start"
        android:layout_marginEnd="@dimen/content_margin_end"
        android:layout_marginTop="@dimen/content_offset">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <android.support.v7.widget.Toolbar
                android:id="@+id/menubar"
                android:layout_width="match_parent"
                android:layout_height="@dimen/menu_bar_size"/>

            <View
                android:layout_width="match_parent"
                android:layout_height="1dp"
                android:layout_marginTop="-1dp"
                android:background="?android:attr/listDivider"/>

            <include layout="@layout/content_main"/>

        </LinearLayout>

    </android.support.v7.widget.CardView>
</RelativeLayout>

その他

FloatingActionButton

layout_anchor で AppBarLayout にぶら下がるようにします。

layout-land/app_bar_main.xml
<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/fab_margin"
    app:layout_anchor="@id/app_bar_layout"
    app:layout_anchorGravity="bottom|end"
    app:srcCompat="@android:drawable/ic_dialog_email"/>

結果

ということで、下図のようなレイアウトを実装できました。リポジトリはこちら
landscape.png

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10