Androidの通知でアニメーションを表示できるのでしょうか?
できるとすればアイコンですよね。
AndroidのNotificationでは SmallIcon
と LargeIcon
の2種類のアイコンを設定できます。
val notification = NotificationCompat.Builder(this, channel.id)
.setSmallIcon(R.drawable.ic_android)
.setLargeIcon(Icon.createWithResource(this, R.drawable.ic_android))
.setContentTitle("Title")
.setContentText("Text")
.build()
notificationManager.notify(1, notification)
これは通知の先頭にも表示されます。LargeIcon
は通知の右側に表示されます。
SmallIcon/LargeIcon のアニメーション
SmallIcon
と LargeIcon
は指定方法が異なります。
SmallIcon
は ResourceID もしくは IconCompat
LargeIcon
は Icon
もしくは Bitmap
Bitmapはアニメーション情報を持たせることはできませんが、 アニメーションリソースを ResourceID として指定したり、そこから作った Icon を渡すことはできます。
SmallIcon
のアニメーションはAndroidユーザーのほとんどの方が見たことがあるはずです。
そのアイコンは、システムリソースに用意されていて、どのアプリからでも使えるようになっています。 android.R.drawable.stat_sys_download
です。
これを指定してみましょう。
val notification = NotificationCompat.Builder(this, channel.id)
.setSmallIcon(android.R.drawable.stat_sys_download)
.setLargeIcon(Icon.createWithResource(this, android.R.drawable.stat_sys_download))
.setContentTitle("Title")
.setContentText("Text")
.build()
はい、ダウンロード中に表示されるアレですね。
これの実体は、 AnimationDrawable
で以下のような定義になっています。
Drawableを複数枚つかったパラパラ漫画ですね。
<?xml version="1.0" encoding="utf-8"?>
<animation-list
xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/stat_sys_download_anim0" android:duration="200" />
<item android:drawable="@drawable/stat_sys_download_anim1" android:duration="200" />
<item android:drawable="@drawable/stat_sys_download_anim2" android:duration="200" />
<item android:drawable="@drawable/stat_sys_download_anim3" android:duration="200" />
<item android:drawable="@drawable/stat_sys_download_anim4" android:duration="200" />
<item android:drawable="@drawable/stat_sys_download_anim5" android:duration="200" />
</animation-list>
SmallIcon
と LargeIcon
は AnimationDrawable
を指定することでアニメーションを表示させることができました。
また、 minSdk に注意が必要ですが、 AnimatedVectorDrawable
を使うことも可能です。ただし、こちらの場合はループ再生はできないみたいです。
RemoteViews にアニメーションアイコンを表示させる
Notification には RemoteViews
を使ったカスタムViewを表示させることができます。
val remoteViews = RemoteViews(packageName, R.layout.notification)
val notification = NotificationCompat.Builder(this, channel.id)
.setSmallIcon(R.drawable.ic_android)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.setCustomContentView(remoteViews)
.build()
RemoteViews は通常の View とは異なり、使用可能な View の種類が限定され、 View に対して行える操作も限定的になります。
以下のように複数の画像を表示させることはできますが
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/stat_sys_download"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/stat_sys_download"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/stat_sys_download"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/stat_sys_download"
/>
</LinearLayout>
アニメーション表示されません。
AnimationDrawable は ImageView に貼り付けただけではアニメーションされず、drawableの start()
メソッドを呼び出す必要がありますが、 RemoteViews の仕組みではこのメソッドを実行することはできません。
では、どうするか?ですが、じつは、 RemoteViews に使える View で勝手にアニメーションしてくれる View があります。
ProgressBar です。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
そして、 ProgressBar のクルクルアニメーションのリソースは android:indeterminateDrawable
で別のアニメーションに差し替えることが可能です。
ということで、以下のようにレイアウトを作ると
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@android:drawable/stat_sys_download"
/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@android:drawable/stat_sys_download"
/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@android:drawable/stat_sys_download"
/>
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@android:drawable/stat_sys_download"
/>
</LinearLayout>
のような形で、自由度の高いレイアウトで、アニメーションを表示させることができます。
通知でのアニメーションは、下手に使うとユーザーに煩わしい印象を持たれてしまいマイナスになりかねませんので、ご利用は計画的に、よく考える必要があります。
ダウンロード中のアイコンのように短時間のステータス表示に使うとか、何か特別なイベントでの演出、のような工夫として使ってみるのであればありかもしれません。
以上です。