MaterialComponentsを使ったお手軽マテリアルデザイン


TECOTEC Advent Calendar 2019の3年連続で19日目担当の柴犬です。

突然ですが皆さん、マテリアルデザイン使ってますか?
マテリアルデザインって何ぞや?って方はこちら

簡単に言うと、ユーザビリティやユーザーの操作を補助するため、Googleさんが推奨しているデザインパターンです。
陰影をつけて立体的に見せたり、ボタンをタップしたときにエフェクトを表示して押してる感を出したり、色々あります。

今回はそのマテリアルデザインをお手軽に扱うことのできるMaterialComponentsの一部を簡単に紹介したいと思います。

開発環境

■AndroidStudio3.5

はじめに

まずはapp/build.gradleを開きましょう。
MaterialComponentsを使用するために以下の確認が必要になります。

compileSdkVersionが28以上かどうか
・AndroidXかそうじゃないかによって、対応するimplementation追加。
※com.google.android.material:materialのバージョンは今回正式リリース版を使います。
 ちなみに2019/12現在の最新は、1.2.0-alpha02です。

終わったらSync Nowしましょう。

app/build.gradle
compileSdkVersion 28以上

dependencies {
    // AndroidXを使用している場合
    implementation 'com.google.android.material:material:1.0.0'

    // AndroidXへ移行できない場合
    implementation 'com.android.support:design:28.0.0'
}

MaterialButton

AppCompatButtonを継承して作られたUIクラスです。
こういう角丸+押下時のエフェクト付きボタンを簡単に実装することが出来ます。

上記のボタンは、以下のように設定して作っています。

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    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=".MainActivity"
    android:padding="20dp">

    <com.google.android.material.button.MaterialButton
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:layout_marginTop="20dp"
        android:layout_gravity="center"
        android:textAllCaps="false"
        android:text="MaterialButton"
        android:textAppearance="@style/TextAppearance.MaterialComponents.Button"
        app:backgroundTint="#4169e1"
        app:cornerRadius="20dp"
        style="@style/Widget.MaterialComponents.Button"/>

</LinearLayout>

必須なのは、android:textAppearancestyle部分です。
後はプロパティの設定で色々変更することが可能です。
主だったプロパティについて記載します。

MaterialButtonプロパティ

プロパティ名 設定内容
backgroundTint ボタンの背景色
cornerRadius ボタンの角丸の値(dp指定)
strokeWidth ボタンの枠線の太さ(dp指定)
strokeColor ボタンの枠線の色
icon ボタンにアイコンを表示する
iconSize アイコンのサイズ(dp指定)
iconTint アイコンの色
iconGravity アイコンの位置(start:ボタン左端、textStart:ボタンテキストの左側)
rippleColor ripple effect(ボタンタップ時の波紋)の色

上記のプロパティをいじるだけで、以下のようなボタンをすぐ作れます。
色々いじって試してみてください!

TextInputLayout + TextInputEditText

お次は入力エリアのMaterialComponentsです。
こんなものが作れます。

最近のモダンなアプリでは、結構取り入れられていると思うコンポーネントの1つです。
選択時に、ヒントテキストがそのままアニメーション付きでタイトルとしてセットされるため
見た目もリッチでユーザインタフェース的にもわかりやすいので、個人的にかなり気に入っています。

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    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=".MainActivity"
    android:padding="20dp">

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox">
        <com.google.android.material.textfield.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="FilledBox"
            android:imeOptions="actionDone"
            android:inputType="textEmailAddress"
            android:maxLines="1"
            android:textSize="14sp" />
    </com.google.android.material.textfield.TextInputLayout>

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        app:passwordToggleEnabled="true"
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
        <com.google.android.material.textfield.TextInputEditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="OutlinedBox"
            android:imeOptions="actionDone"
            android:inputType="textPassword"
            android:maxLines="1"
            android:textSize="14sp" />
    </com.google.android.material.textfield.TextInputLayout>

</LinearLayout>

使い方は至ってシンプル。
TextInputLayoutの中にTextInputEditTextネストし、
TextInputLayoutstyleをセットするだけです。

styleには、FilledBox(入力エリアが塗りつぶされている)とOutlinedBox(入力エリアが枠線付き)が用意されています。
後は先程のMaterialButtonと同様に、TextInputLayoutのプロパティでさらに細かい部分までいじることが出来ます。
こちらも主だったプロパティについて記載します。

TextInputLayoutプロパティ

プロパティ名 設定内容
boxCornerRadius○○ 四辺の角丸設定(左上:TopStart、左下:BottomStart、右上:TopEnd、右下:BottomEnd)
boxBackgroundColor 入力エリア内の色
boxStrokeColor 入力エリアの枠線の色(OutlinedBox時のみ有効)
helperText 入力時の補助となる文言を指定
hintAnimationEnabled ヒントがそのままタイトルに移る際のアニメーションON/OFF
passwordToggleEnabled パスワードのトグルを有効にするかどうか(ネストされているTextInputEditText->inputTypeをpassword関連にした場合のみ有効)
passwordToggleTint パスワードトグルの色
counterEnabled 入力文字数を表示するかどうか
counterMaxLength 入力文字数の最大値をセットする。入力文字数1/10みたいなのが作れる(counterEnabledがtrueの場合のみ有効)

ChipGroup(Chip)

最後はChipGroupのご紹介です。
関連タグや検索候補などを表示するときに使ったりするMaterialComponentsです。
見た目的にはこういうものになります。

xml上での定義は以下のようになります。

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    android:orientation="vertical"
    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=".MainActivity"
    android:padding="20dp">

    <com.google.android.material.chip.ChipGroup
        android:id="@+id/chipGroup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:singleSelection="true">
        <com.google.android.material.chip.Chip
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="黒柴"
            android:textSize="12sp"
            android:textAppearance="@style/TextAppearance.AppCompat.Small"
            style="@style/Widget.MaterialComponents.Chip.Action"/>
        <com.google.android.material.chip.Chip
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="白柴"
            android:textSize="12sp"
            android:textAppearance="@style/TextAppearance.AppCompat.Small"
            style="@style/Widget.MaterialComponents.Chip.Entry"/>
        <com.google.android.material.chip.Chip
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="赤柴"
            android:textSize="12sp"
            android:textAppearance="@style/TextAppearance.AppCompat.Small"
            style="@style/Widget.MaterialComponents.Chip.Filter"/>
        <com.google.android.material.chip.Chip
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="豆柴"
            android:textSize="12sp"
            android:textAppearance="@style/TextAppearance.AppCompat.Small"
            style="@style/Widget.MaterialComponents.Chip.Choice"/>
    </com.google.android.material.chip.ChipGroup>

</LinearLayout>

ChipGroupの中にChipをネストすることで、1つのグループとして管理することができるようになります。
グループとして管理する必要がない場合、Chipだけで使用することもできます。
感覚としてはRadioGroupRadioButtonの関係性に近いです。

各Chipにはstyleとして、【.Chip.Action】【.Chip.Entry】【.Chip.Filter】【.Chip.Choice】のどれかを指定して使います。
これらの違いは、タップしたときの選択状態・閉じるボタンの有無などになります。

それぞれの主なプロパティの説明を上げておきます。

ChipGroupプロパティ

プロパティ名 設定内容
checkedChip 指定したIDのChipをチェック状態にする
chipSpacing,chipSpacing○○ Chip同士の間隔をセット。Horizontalで横、Verticalで縦のみにも指定可能(dp指定)
singleLine 1行以上表示できるかどうか(デフォルトはfalse)
singleSelection Chipを1つ以上選択できるかどうか(デフォルトはfalse)

Chipプロパティ

プロパティ名 設定内容
chipIcon,closeIcon Chipにアイコンを表示する
chipIconSize, closeIconSize アイコンのサイズ(dp指定)
chipIconTint, closeIconTint アイコンの色
rippleColor ripple effect(ボタンタップ時の波紋)の色
chipCornerRadius Chipの角丸の値(dp指定)
chipBackgroundColor Chipの背景色
chipStrokeWidth Chipの枠線の太さ(dp指定)
chipStrokeColor Chipの枠線の色

こちらのComponentにはsetOnClickListenerの他にも
setOnCheckedChangeListener, setOnCloseIconClickListenerなどといった
チェック時や閉じるボタンの動作を検知するためのリスナーも用意されていますので、
用途によって色々な実装をすることも可能です。

おわりに

いかがだったでしょうか?
それぞれ、自分でイチから実装しようと思うと、基本の機能を拡張したり、アニメーションさせたりとてつもなく面倒ですが、
xmlへの定義だけで、これだけのコンポーネントが使えるのは素直にスゴいですよね!!
今後も定期的に追加されていくはずなので楽しみです。

今回はソース側からの操作については記載しませんが、他にも色々できるのでぜひご自身で試してみてください!