Ripple effectとは、Materialデザインのアニメーションの1つで、波紋が広がるような表現のことです。Googleの公開したMaterial Designの動画を見ると、タップした時のフィードバックだけでなく、ビューの切り替えや画面遷移などにも幅広く対応できるエフェクトのようです。
そのRippleエフェクトを、Android5.0未満でも動作するように実装してみました。
ライブラリを使う
material-rippleというライブラリを使いました。
RippleEffectというのもあるんですが、material-rippleの方が使いやすかったです。
特に使いやすかったポイントは以下3点。
- エフェクト完了後に状態をそのままにするか(
app:ripplePersistent
)、タップした時にhoverエフェクトもつけるか(app:rippleHover
)といったオプションが多い。 - タップ後に画面遷移が入る場合、デフォルトでRippleエフェクトが完了してから遷移してくれる。RippleEffectの方は、エフェクトが始まった瞬間に画面遷移してしまう。
- xmlだけでなく、コードでエフェクトをつけることもできる。
MaterialRippleLayout.on(view).rippleColor(Color.BLACK).create();
両方とも、Rippleをつけたい要素をViewで囲って実装する点では同じです。
<com.balysv.materialripple.MaterialRippleLayout
android:id="@+id/ripple"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Button inside a ripple"/>
</com.balysv.materialripple.MaterialRippleLayout>
MaterialRippleLayout
はFrameLayoutの拡張クラスなので、中に入る要素は1つでなければいけません。つまり、必ずネストが1つ増えます。パフォーマンスが気になるかもしれませんが、前に実験した限りそこまで問題なさそうだったので目をつむりました。
Viewのネストはどのくらい遅いのか ー 12階層のレイアウトを5階層にして検証してみた
MaterialRippleLayoutで囲ってやればすぐエフェクトがつくようになるので、あとはReadMeを見ながら色や時間を調整すればOKです。
そもそも対応すべきなのか?
一応できたんですが、正直Android5.0未満では対応しない方がいいんじゃないかなという意見です。
Google純正のアプリや他の有名なアプリはAndroid5.0以上で対応していて、5.0未満は諦めてます。というより、たぶんあえてやってないのだと思います。
Materialデザインガイドラインの本質は、画面を似せることではなく、同じ基準で作ることによってユーザーが操作する時に頭を使わないですむようにすることだと思うので、Android5.0未満のRippleエフェクトが標準でない端末の場合はむしろ従来のタップフィードバックの方がいいよねという判断なのではないでしょうか。勘なので、本当はただめんどくさいだけかも。。。
とりあえず対応できることはわかったので、実際に対応するかはユーザーを元に判断しようと思います。