はじめに
マテリアルデザインの公式ライブラリ「Material Components Android」ですが、新機能が続々と登場しています。今回はその中のBadgeにテーマを絞って、Component別のBadgeの実装方法について説明していきます。
Badgeとは
Badgeとは、通知の件数表示などに使われるコンポーネントです。
Badgeには以下のように三種類の表示形式があり、これらを実装するためのAPIが公式のMaterial Components Androidで提供されています。
Badgeについてはこちらの公式ドキュメントにて詳しく解説されています。
BottomNavigation | Material Design
Badgeの種類
Badgeの種類は以下の3種類になります。
1. ドット
デフォルトでの表示になります。
2. 数字付き
通知の未読件数を表示したい時などに便利です、
3. 数字付き(最大値を超えた場合)
指定した最大文字数を超えると、以下のように+
マークが後ろに付与されます。
何も指定しなくても最大値は設定されていて、デフォルトでは3桁(999)が最大になります。
BadgeDrawable
Material Components AndroidでBadgeを実装するにはBadgeDrawableというクラスを使って実装します。公式のドキュメントは以下になります。
BadgeDrawable | Material Design
今の所こちらのBadgeDrawableによるBadge表示のAPIを提供しているコンポーネントは以下になります。これらのコンポーネントについては、バッジを付与するための独自のカスタムビューなどを作成せずともバッジの実装が可能になります。(※material-component-android-1.1.0-alpha10時点)
- BottomNavigation
- TabLayout
今後もMaterialComponentは新機能が追加されていく可能性があるので、こちらのリポジトリをwatchしておくと良さそうです。
下準備
では早速実装方法について見ていきます。まずは下準備としてbuild.gradle
にdependenciesを追加します。
app/build.gradle
のdependenciesを追加
まず、app配下のbuild.gradleにdependenciesを追加します。今回は、現時点での最新のmaterialcomponents1.1.0-alpha10
を使用します。
// 省略
dependencies {
...
implementation 'com.google.android.material:material:1.1.0-alpha10' // こちらを追加
}
アプリのThemeはTheme.MaterialComponents
を継承したものを使う
MaterialComponentsを使用するためには、アプリのThemeにTheme.MaterialComponents.*
のものを指定しなければなりません。
例えば、以下のようにThemeを設定する必要があります。
<!-- Theme.AppCompat.Light.DarkActionBar ではない -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
...
</style>
コンポーネント別Badgeの付与方法
BottomNavigation
Badgeの表示
getOrCreateBadge(menuItemId)
メソッドを使います。
引数には、BottomNavigationに設定されているmenuItemの中で、表示したいitemIdを指定します。
※1.1.0-alpha08で、showBadge()
からリネームされているので要注意です。
getBadge(menuItemId)
というメソッドもありますが、こちらは取得のみのメソッドなので、バッジがmenuItemにアタッチされていない場合もあります。そのため、返り値がNullableです。NonNullで取得したい場合はgetOrCreateBadge()
を使うのが良さそうです。
Badgeの非表示
removeBadge(menuItemId)
メソッドを使います。
引数には、BottomNavigationに設定されているmenuItemの中で、非表示にしたいitemIdを指定します。
// 表示
val notificationMenuItem = binding.bottomNav.menu.item(NOTIFICATION_ITEM_ID) // Badgeを付与したいmenuItemを取得
notificationMenuItem?.let {
binding.bottomNav.orCreateBadge(it.itemId)
}
// 非表示
notificationMenuItem?.let {
binding.bottomNav.removeBadge(it.itemId)
}
TabLayout
Badgeの表示
TabLayoutのTabクラスにBadgeDrawableを使用するためのAPIが提供されています。
tab.getOrCreateBadge()
メソッドを使って、BadgeDrawableを作成します。
Kotlinで書くとプロパティアクセス的に書けてしまうので、実際にはtab.orCreateBadge
と書くことになります。
※1.1.0-alpha08で、showBadge()
からリネームされているようですので要注意です。
また、バッジの取得にはgetBadge()
メソッドがありますが、こちらはnullableアノテーションがついているので、nonnullで扱いたい場合は、基本的にgetOrCreateBadge()
を使うのが良さそうです。
Badgeの非表示
removeBadge()
メソッドを使います。
// 表示
val badge = tab.orCreateBadge
// 非表示
tab.removeBadge()
Badgeのオプション設定
基本的にどちらのコンポーネントでもBadgeDrawableを取得した後のオプション設定方法は共通なので、こちらでまとめて紹介していきます。
数字の設定
数字の付与にはsetNumber()
メソッドを使います。
val notificationMenuItem = binding.bottomNav.menu.item(NOTIFICATION_ITEM_ID)
notificationMenuItem?.let {
val badge = binding.bottomNav.orCreateBadge(it.itemId)
badge.number = 10 // バッジに表示する数字の付与
}
clearNumber()
というメソッドもありますが、こちらは、数字付きのBadgeが数字なしのBadge表示に変わるだけなので、普通にバッジを削除したいのであれば、Badgeがついている親Viewに実装されているremoveBadge()
を呼び出しましょう。
最大値の設定
最大値の設定はバッジに表示される文字数で指定します。つまり+
文字がデフォルトで入るので、(最大桁数+1)の数字になります。
setMaxCharacterCount()
を使って、Badgeの最大表示文字数を指定します。
val notificationMenuItem = binding.bottomNav.menu.item(NOTIFICATION_ITEM_ID) // Badgeを付与したいmenuItemを取得
notificationMenuItem?.let {
val badge = binding.bottomNav.orCreateBadge(it.itemId)
badge.number = data.count()
badge.maxCharacterCount = 3 // 最大表示文字数の指定。この場合99が最大件数。
色の設定
バッジの背景色は、setBackgroundColor()
メソッドを使います。
バッジのテキストの色は、setBadgeTextColor()
メソッドを使います。
val notificationMenuItem = binding.bottomNav.menu.item(NOTIFICATION_ITEM_ID)
notificationMenuItem?.let {
// ↓applyを使った方が綺麗に書けます。
val badge = binding.bottomNav.orCreateBadge(it.itemId)
badge.backgroundColor
= ContextCompat.getColor(context, R.color.bottom_nav_badge_background_red) // 背景色の指定
badge.badgeTextColor
= ContextCompat.getColor(context, R.color.bottom_nav_badge_text_white) // テキストの色の指定
まとめ
公式のライブラリでバッジをサポートしてくれるとコードの記述量を削減できますし、マテリアルデザインに沿って、レイアウトしてくれるのでとてもありがたいです。
今後もバージョンアップがあれば更新していこうと思います。最後までご覧いただきありがとうございました。