標準のRipple Effectのまとめ


概要

Ripple Effectは直訳すると波紋効果です。
マテリアルデザインなどで、UI要素をタップしたときに波紋を表示して視覚的にわかりやすく伝えるためのエフェクトです。
・UI要素の周りに表示

・UI要素の内部に表示


独自のアニメーションをxmlで自作することもできますが、今回は標準で用意されているエフェクトのまとめです。
[参考URL]
・カスタム アニメーションの定義
https://developer.android.com/training/material/animations?hl=ja
・RippleDrawable(自作する場合はこちら)
https://developer.android.com/reference/android/graphics/drawable/RippleDrawable?hl=ja

標準のRipple Effect

  • ?android:attr/selectableItemBackground
    • 範囲が限定された波紋
  • ?android:attr/selectableItemBackgroundBorderless
    • ビューの範囲外まで広がる波紋

(注意)どちらもAPI Level 21 (Android 5.0)から使用可能

設置方法

  • background
    • selectableItemBackgroundBorderlessでUI要素の外まで波紋を表示可能
  • foreground
    • backgroundでcolorなどを指定していても使用可能
    • (注意)API Level 23 (Android 6.0)から使用可能

サンプルGIF画像

サンプルはImageViewに表示していますが、タップを許可しているUI要素ならButtonでもLinearLayoutでも可能です。

[1] android:background="?attr/selectableItemBackground"

UI要素内にエフェクトを表示

[2] android:foreground="?attr/selectableItemBackground"

UI要素内にエフェクトを表示
backgroundも設定可能(android:background="@color/purple_200")

[3] android:background="?attr/selectableItemBackgroundBorderless"

UI要素を覆うように円形のエフェクトを表示
こちらのサンプルは上サンプルと同じくlayout_widthが長めなので円も大きめ
トップのサンプルのように小さくする場合は画像とUI要素のサイズを近くする

[4] android:foreground="?attr/selectableItemBackgroundBorderless"

UI要素内にエフェクトを表示
backgroundも設定可能(android:background="@color/purple_200")
foregroundはUI要素内に波紋が収まるので、結果[2]と同一の見た目になる

[5] 応用編 タップ領域を広げたいけどエフェクトは内部のUI要素のみに適応

エフェクトを表示したいUI要素に設定すれば、囲んでいる親領域をタップした時も反応してくれる
一応エフェクトを設定したUI要素が複数あっても反応してくれる

サンプルXML

上記サンプルのXMLです
そのままAndroidStudioにぺたりと貼り付ければテスト可能です

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">

    <!-- [1] -->
    <ImageView
        android:id="@+id/test1_image_view"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_marginTop="20dp"
        android:background="?attr/selectableItemBackground"
        android:clickable="true"
        android:focusable="true"
        android:orientation="horizontal"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <!-- [2] -->
    <ImageView
        android:id="@+id/test2_image_view"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_marginTop="20dp"
        android:background="@color/purple_200"
        android:clickable="true"
        android:focusable="true"
        android:foreground="?attr/selectableItemBackground"
        android:orientation="horizontal"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/test1_image_view" />

    <!-- [3] -->
    <ImageView
        android:id="@+id/test3_image_view"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_marginTop="100dp"
        android:background="?attr/selectableItemBackgroundBorderless"
        android:clickable="true"
        android:focusable="true"
        android:orientation="horizontal"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/test2_image_view" />

    <!-- [4] -->
    <ImageView
        android:id="@+id/test4_image_view"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_marginTop="100dp"
        android:background="@color/purple_200"
        android:clickable="true"
        android:focusable="true"
        android:foreground="?attr/selectableItemBackgroundBorderless"
        android:orientation="horizontal"
        android:src="@mipmap/ic_launcher"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/test3_image_view" />

    <!-- [5] -->
    <LinearLayout
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="50dp"
        android:background="@color/purple_200"
        android:clickable="true"
        android:focusable="true"
        android:gravity="center"
        android:orientation="horizontal"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/test4_image_view">

        <ImageView
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="?attr/selectableItemBackgroundBorderless"
            android:src="@mipmap/ic_launcher" />
    </LinearLayout>

</androidx.constraintlayout.widget.ConstraintLayout>