チームBLUECODEの開発ブログ

開発の中で生まれたtipsを共有していきます。

Androidアプリで背景が透明な画像にRipple Effectをつける男

bluecodeのいーちゃんです。

タイトルの通りAndroidアプリの中で背景が透明な画像にRipple Effectをつけたい場面があったんですが、少し詰まったので載せておきます。

こんなんです。(画像だとrippleがわかりにくいですが)

f:id:team-bluecode:20190204025725p:plain:w200
タップ前
f:id:team-bluecode:20190204025736p:plain:w200
タップ時


Toolbarウィジェットを使えば自動的にエフェクトがつきますが、ここでは全て自前で、かつ汎用的に使える手段を記載します。


Activityに関して特筆事項はありませんが一応載せておきます。
この画面に遷移するためだけのMainActivityもあるとして、SubActivityとしています。
[SubActivity]

class SubActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.sub_activity)

        findViewById<View>(R.id.sub_activity_back_button).setOnClickListener {
            finish()
        }
    }
}



Effectをかけたい範囲をFrameLayoutで指定し、背景をbackground="@drawable/background_selector_shape_oval_white]"で指定します
[sub_activity.xml]

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#443a59">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="?actionBarSize"
        android:orientation="horizontal">

        <FrameLayout
            android:id="@+id/sub_activity_back_button"
            android:layout_width="36dp"
            android:layout_height="36dp"
            android:layout_gravity="center_vertical"
            android:layout_marginLeft="12dp"
            android:background="@drawable/background_selector_shape_oval_white">

            <ImageView
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:layout_gravity="center"
                android:contentDescription="@null"
                android:src="@drawable/icn_actionbar_back_button" />
        </FrameLayout>
    </LinearLayout>
</FrameLayout>



ここからがポイントです。
コード内にコメントしていますが背景が透明な時はmaskの指定が必要になります。背景が透明でなければ不要です。
maskは指定しなかった場合は対象の背景部分が波紋の広がる範囲となるため、背景が透明だとエフェクトもみえません。
[background_selector_shape_oval_white]

<!-- タップ時にoval型の#59FFFFFF色の波紋を出すレイアウト(デフォルト透明) -->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="#59FFFFFF">
    <!-- デフォルト色がtransparentの場合はmask指定が必要 -->
    <item android:id="@android:id/mask">
        <shape android:shape="oval">
            <!-- ここのcolorは指定が必要だが反映はされない -->
            <solid android:color="@android:color/white" />
        </shape>
    </item>
    <!-- デフォルト状態の背景 -->
    <item>
        <shape android:shape="oval">
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>
</ripple>


これで画像のように画像タップ時に半透明な白色の円形のエフェクトを見せることができます。
色や形をカスタムしたい場合は[background_selector_shape_oval_white]で指定するshapeやcolorを任意に変更してください。



ただしrippleエフェクトが機能するのはtargetSdk21以降のみになります。
targetSdkが21未満の場合は[background_selector_shape_oval_white]ファイルをres/drawable-v21配下に移し、res/drawable配下に同じファイル名で下記のようなファイルを追加して、押下時に背景色が変わる処理を入れてあげると良いでしょう。

[res/drawable/background_selector_shape_oval_white]

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- pressed -->
    <item android:drawable="@drawable/background_shape_oval_white" android:state_enabled="true" android:state_pressed="true" />
    <!-- default -->
    <item android:drawable="@android:color/transparent" />
</selector>

[background_shape_oval_white]

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#59FFFFFF" />
</shape>


drawableファイルでselector指定するところとか冗長でめんどくさいですよね

以上です。あざっした。