[Android] SnackbarをBuilderパターンっぽく表示したい
目次
2022年の今、遅きに失したというか今更感があるんですが…。AndroidのSnackbarについて、テキストの色、背景色、アクションなどよく変更する設定をBuilderパターンっぽく書きたいなと思いまして、ちょっと試してみました、というのがこの記事です。
Builderクラスを作るパターン
最初に試したのが、SnackbarBuilderというクラスを作るパターン(ソースコードは後述します)。本当は Snackbar.Builder()
というようにBuilderのコンストラクタを呼び出したかったのですが、Kotlinの文法ではいい感じにできなさそうです。そのため、SnackbarBuilderというクラスを作った、というのがこのパターンです。
SnackbarBuilder()
.view(view)
.text("Awesome Text")
.textColor(R.color.text_color)
.backgroundColor(R.color.background_color)
.length(Snackbar.LENGTH_LONG)
.action("Action") { /* TODO */ }
.actionTextColor(R.color.text_color)
.build()
.show()
本来やりたかったことがだいたいできているんですが、viewとtextは必須にしたいです(lengthはデフォルト値を決めておけば必須でなくても良い)。SnackbarBuilderのコンストラクタでviewとtextを受け取るようにもできますが、それならば標準で用意されている Snackbar#make
を使った方が筋が良さそうです。
ということで、没案となったSnackbarBuilderの(実験的な)ソースコードはこちらです。このコードブロックのあとに改善版を示しますので、改善版をすぐに見たい方は急いでスクロールしてください。
class SnackBarBuilder {
private var view: View? = null
private var string: String? = null
@ColorRes private var textColor: Int? = null
@ColorRes private var backgroundColor: Int? = null
private var length: Int = Snackbar.LENGTH_SHORT
private var actionString: String? = null
private var action: ((View) -> Unit)? = null
@ColorRes private var actionTextColor: Int? = null
fun view(view: View): SnackBarBuilder =
this.also {
it.view = view
}
fun text(string: String): SnackBarBuilder =
this.also {
it.string = string
}
fun textColor(@ColorRes textColor: Int): SnackBarBuilder =
this.also {
it.textColor = textColor
}
fun backgroundColor(@ColorRes backgroundColor: Int): SnackBarBuilder =
this.also {
it.backgroundColor = backgroundColor
}
fun length(length: Int): SnackBarBuilder =
this.also {
it.length = length
}
fun action(actionText: String, action: (View) -> Unit): SnackBarBuilder =
this.also {
it.actionString = actionText
it.action = action
}
fun actionTextColor(@ColorRes actionTextColor: Int): SnackBarBuilder =
this.also {
it.actionTextColor = actionTextColor
}
fun build(): Snackbar {
val view = requireNotNull(view)
val string = requireNotNull(string)
val snackBar = Snackbar.make(view, string, length)
if (textColor != null) {
snackBar.view
.findViewById<TextView>(R.id.snackbar_text)
.setTextColor(
ContextCompat.getColor(view.context, requireNotNull(textColor))
)
}
if (backgroundColor != null) {
snackBar.view
.setBackgroundColor(
ContextCompat.getColor(view.context, requireNotNull(backgroundColor))
)
}
if (actionString != null && action != null) {
snackBar.setAction(actionString, action)
}
if (actionTextColor != null) {
snackBar.setActionTextColor(
ContextCompat.getColor(view.context, requireNotNull(actionTextColor))
)
}
return snackBar
}
}
長い!
拡張関数で頑張るパターン
次に試したのが、Kotlinの拡張関数で頑張るパターンです。こちらのパターンは、標準で用意されている Snackbar#make
を使ってSnackbarのインスタンスを生成した後、その他の属性値をBuilderパターンっぽく渡せるようにしています。とりあえずは、この実装で満足しました。
Snackbar.make(view, "Awesome Text", Snackbar.LENGTH_LONG)
.textColor(R.color.text_color)
.backgroundColor(R.color.background_color)
.action("Action") { /* TODO */ }
.actionTextColor(R.color.text_color)
.show()
Kotlinの拡張関数で頑張るパターンのソースコードを以下に示します。Snackbarに対して自身を返す拡張関数を定義して、 also
内で追加の属性値を設定しています。先程の実装よりもこちらの実装の方が短く書けますね。
fun Snackbar.textColor(@ColorRes color: Int): Snackbar =
this.also {
it.view
.findViewById<TextView>(R.id.snackbar_text)
.setTextColor(ContextCompat.getColor(context, color))
}
fun Snackbar.backgroundColor(@ColorRes color: Int): Snackbar =
this.also {
it.view
.setBackgroundColor(ContextCompat.getColor(context, color))
}
fun Snackbar.action(text: String, action: (View) -> Unit): Snackbar =
this.also {
it.setAction(text, action)
}
fun Snackbar.actionTextColor(@ColorRes color: Int): Snackbar =
this.also {
it.setActionTextColor(ContextCompat.getColor(context, color))
}
今更感がすごいですが、きれいに書けるようになって自分的には満足です。
書いている人 😎

茨城県つくば市在住のモバイルアプリケーションアーキテクト(Androidが得意です)。モバイルアプリのアーキテクチャ、自動テスト、CI/CDに興味があります。いわゆる「レガシーコード」のリファクタリング・リアーキテクチャが好きです。
👉 もっと詳しく
著書 ✍
Android 依存性注入 ヒッチハイク・ガイド🧳
Androidアプリでの依存性注入(Dependency Injection)に入門するためのガイダンスです。依存性注入の概念やメリットを理解し、Dagger Hiltを用いてAndroidアプリに適用する方法を解説しています。
ソフトウェアデザイン 2023年6月号📚
特集「クリーンアーキテクチャとは何か?」の第5章「モバイルアプリ開発における実践」を執筆しました。
Android クリーンアーキテクチャ ヒッチハイク・ガイド🧳
Androidアプリでのクリーンアーキテクチャに入門するためのガイダンスです。クリーンアーキテクチャの概念を理解し、Androidアプリに適用する方法を解説しています。
Android ユニットテスト ヒッチハイク・ガイド🧳
Androidアプリのユニットテストに入門するためのガイダンスです。初学者が混乱せずにAndroidアプリのユニットテストを書き始めることができる、ということを目的としています。
Android MVVMアーキテクチャ入門🛠
Androidアプリ開発の初学者に向けた、MVVM(Model-View-ViewModel)アーキテクチャの入門書を書きました。初学者の方を確実にネクストレベルに引き上げる技術書です。NextPublishingより出版されています。
関連記事 👀
- GitHub ActionsでSonarCloudにカバレッジをアップロードする
- [Android] Uniflowを用いたMVI的なアーキテクチャを試してみる🦄
- [Android] 単体テスト用の依存関係をHiltで解決する
- 俺のパブリックリポジトリ
- GitHub ActionsでktlintとAndroid Lintを並列実行して、DangerでPRにまとめてコメントする🐝