CoordinatorLayoutで作るマテリアルデザインとカスタム方法の基礎

この記事は、 eureka Advent Calendar 2017 18日目 の記事です。

eureka Advent Calendar 2017 17日目の記事は、 僕が普段お世話になっている @futabooo さんの 読書メーターのAndroidアプリを勝手に作ってたら公式がリリースされた話 でした。

はじめに

こんにちは。皆さん、はじめまして。

エウレカのPairs事業部にてAndroidエンジニアとしてインターンしている鈴木です。

今回は CoordinatorLayoutで作るマテリアルデザインとカスタム方法の基礎 について実際にPairsに取り入れていることについてお話しします。

僕自身初めて触って実装した部分で、この記事はCoordinatorLayoutに興味があって初めて触る人を対象にしているので 初心者向け です。

この記事で紹介すること

  • マテリアルデザインとは?
  • CoordinatorLayout
    • 概要
    • サンプル
      • 通常のもの
      • スクロール動作に合わせてカスタムする
        • 1.背景を変更する場合
        • 2.タイトルの文字色を変更する場合
        • 3.NavigationIconを動的に変更したい場合
        • 4.背景を画像にしたい場合
  • 引用・参考
  • さいごに

マテリアルデザインとは?

Googleが2014年から発表しているデザインのガイドラインです。

Material Design – Introductionから、簡単にまとめるとユーザーが直感的に分かるために統一感を持たせ操作を分かりやすくしたデザインです。

今回はそんなマテリアルデザインを実際にPairsに取り入れ実装した部分で、 CoordinatorLayout の機能とカスタム方法を自分なりにまとめてみましたので紹介します。

CoordinatorLayout

概要

CoordinatorLayoutはCoordinatorLayout – developer.android.comにもある通り、ViewGroupの一種でGooglePlayStoreやモダンなアプリによくあるスクロールの挙動に合わせて見え隠れしたりするLayoutです。

画像1: GooglePlayStoreサンプル

実際にKotlinでサンプルを作成したので紹介していきたいと思います。

サンプル

通常のもの

CoordinatorLayoutを実装していくにあたって標準で用意されているサンプルを元に作成していきました。
AndroidStudioのFile > New > New Projectの中にあるScrollingActivityの実装とほぼ同じです。
ここの部分は既にやってらっしゃる方の記事を参考にしていますので簡潔に説明致します。

スクロールの動作に合わせて折りたたみ動作を再現しています。

画像2: CoordinatorLayout – exitUntilCollapsed

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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:expandedTitleTextAppearance="@style/TextAppearance.Design.CollapsingToolbar.Expanded.Expanded2">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin" />

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

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

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

CollapsingToolbarLayoutでapp:layout_scrollFlags="scroll|exitUntilCollapsed"
を指定してやると画像2のようにToolbarの高さまで折りたたんでくれます。

上のToolbarの高さも表示したくない場合はapp:layout_scrollFlags="scroll|enterAlwaysCollapsed"
を指定してやると以下のように作成できます。

画像3: CoordinatorLayout – enterAlwaysCollapsed

enterAlwaysCollapsedでは一番上までスクロールしないと折りたたみ動作がされません。
逆に一番上まで行かなくてもスクロールによって折りたたみ動作を実現したい、かつToolbarの高さをも折りたたみたいときはapp:layout_scrollFlags="scroll|enterAlways"を指定してやると以下のよう作成できます。

画像4: CoordinatorLayout – enterAlways

次はスクロールの動作に合わせてカスタムしていく方法を紹介します。

スクロール動作に合わせてカスタムする

次にスクロールの動作に合わせて色を変更する方法を紹介していきたいと思います。

まずは以下をご覧ください。

画像5: CoordinatorLayout – custom
1. 背景を変更する場合

CollapsingToolbarLayoutのandroid:background="@android:color/holo_purple"のようにするとスクロールで表示が拡大した際の背景を変更できます。今回は紫色にしているので上記のカラーを指定しています。

逆に折りたたんだ時の背景を変更したい場合は、app:contentScrim="@color/colorPrimary"のようにするとスクロールしてToolbarの高さになった時の背景を変更することができます。今回はデフォルトのカラーを指定しています。

2. タイトルの文字色を変更する場合

styles.xmlにてstyleをまず用意します。

拡大した時はparent="TextAppearance.Design.CollapsingToolbar.Expanded"を指定したstyleを用意し、縮小するときにはparent="TextAppearance.Design.CollapsingToolbar.Collapsed"を指定したstyleを用意します。

    <style name="TextAppearance.Design.CollapsingToolbar.Expanded" parent="TextAppearance.Design.CollapsingToolbar.Expanded">
        <item name="android:textColor">@android:color/white</item>
        <item name="android:textSize">25sp</item>
    </style>

    <style name="TextAppearance.Design.CollapsingToolbar.Collapsed" parent="TextAppearance.Design.CollapsingToolbar.Collapsed">
        <item name="android:textColor">@android:color/black</item>
        <item name="android:textSize">20sp</item>
    </style>

上記のようにして、ここで変えたいテキストのカラーをandroid:textColorの部分で指定する必要があります。

文字の大きさも変更したい場合はandroid:textSizeで変えたい文字の大きさに変更できます。

次に、CollapsingToolbarLayoutの中で上で作成したスタイルを拡大、縮小に合わせて指定する必要があります。

縮小する場合はapp:collapsedTitleTextAppearance="@style/TextAppearance.Design.CollapsingToolbar.Collapsed"を指定し、拡大する場合はapp:expandedTitleTextAppearance="@style/TextAppearance.Design.CollapsingToolbar.Expanded"のように指定することでタイトルテキスト色とサイズの変更ができます。

3. NavigationIconを動的に変更したい場合

画像5で見てもらったようにスクロールの動作に合わせてNavigationIconを動的に変更する方法を紹介します。

コードで以下のように指定する必要があります。

val toolbar = findViewById(R.id.toolbar) as Toolbar
val appBar = findViewById(R.id.app_bar) as AppBarLayout
var scrollRange = -1
appBar.addOnOffsetChangedListener { appBarLayout, verticalOffset ->
 if (scrollRange == -1) {
   scrollRange = appBarLayout.totalScrollRange
  }
 if (scrollRange + verticalOffset != 0) {
   toolbar.navigationIcon = resources.getDrawable(R.drawable.ic_arrow_back_white)
  } else {
   toolbar.navigationIcon = resources.getDrawable(R.drawable.ic_arrow_back_black)
  }
}

appBarLayout.totalScrollRangeでappBarLayoutのスクロール範囲を取得でき、verticalOffsetがスクロールによって変化するため

scrollRange + verticalOffset = 0つまりToolbarの高さまで縮小した際にNavigationIconの出し分けを行なっています。

画像で見ると以下のようなイメージです。

画像6: AppBarLayoutのスクロール範囲イメージ図
4. 背景を画像にしたい場合

次によくある拡大されている部分に背景画像を追加したい時、どのように実現するかについてお話しします。

以下は背景画像を追加した際のサンプルです。

画像7: CoordinatorLayout – Imageを追加した場合のサンプル

この場合は、CollapsingToolbarLayoutの中でImageViewを下記のように追加する必要があります。

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="180dp"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:contentScrim="@color/colorPrimary"
            app:collapsedTitleTextAppearance="@style/TextAppearance.Design.CollapsingToolbar.Collapsed"
            app:expandedTitleTextAppearance="@style/TextAppearance.Design.CollapsingToolbar.Expanded">

            // ここに追加
            <ImageView
                android:id="@+id/image"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                android:src="@drawable/office"/>


            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin" />

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

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

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

こうすることで自分が指定した画像を拡大時に設定することができます。

また、この画像を少し暗くしたい時などはコード上で以下のようにImageViewに用意されているColorFilterを設定するためのメソッドsetColorFilterで以下のように指定することで実現できます。

image.setColorFilter(ContextCompat.getColor(applicationContext, R.color.black_alpha), PorterDuff.Mode.SRC_ATOP)

画像8: 画像に暗みを掛けた際のサンプル

画像7に比べて画像に暗みがかかっているのが分かると思います。

引用・参考

さいごに

今回は実際にPairs JPにも取り入れている部分であるCoordinatorLayoutの実装とカスタムの仕方についての紹介でした。
サンプルのコードはこちらにあるのでクローンしてビルドしてもらえれば出来ると思います。
意外と簡単に実装できるのでぜひ試してみてはいかがでしょうか。

明日の記事は、同じチームでお世話になっている@JohnEstropia さんのRxSwift Tips and Tricksです。
お楽しみに!

  • このエントリーをはてなブックマークに追加

エウレカでは、一緒に働いていただける方を絶賛募集中です。募集中の職種はこちらからご確認ください!皆様のエントリーをお待ちしております!

Recommend

エンジニアの僕が絶対やるJIRAの4つの設定

社内Tinder風Webアプリ「Maybee」を会社忘年会のイベント用に作った話