【Jetpack Compose】Compose Settings で数分で設定画面を作る

意外と面倒な設定画面が数分でできます。

This library provides a set of Settings like composable items to help android Jetpack Compose developers build complex settings screens without all the boilerplate

このライブラリは、開発者がボイラープレートなしで複雑な設定画面を構成できるアイテム詰め合わせです。

👉 alorma/Compose-Settings: Android #JetpackCompose Settings library hatena-bookmark

以下コピペですぐに表示できます。


implementation 'com.github.alorma:compose-settings-ui:$version'


SettingsMenuLink(
  icon = { Icon(imageVector = Icons.Default.Wifi, contentDescription = "Wifi") },
  title = { Text(text = "Link") },
  subtitle = { Text(text = "This is a longer text") },
  onClick = {},
)
Divider()
SettingsSwitch(
  icon = { Icon(imageVector = Icons.Default.Wifi, contentDescription = "Wifi") },
  title = { Text(text = "Switch") },
  subtitle = { Text(text = "This is a longer text") },
  onCheckedChange = { },
)
Divider()
SettingsCheckbox(
  icon = { Icon(imageVector = Icons.Default.Wifi, contentDescription = "Wifi") },
  title = { Text(text = "Checkbox") },
  subtitle = { Text(text = "This is a longer text") },
  onCheckedChange = { },
)
Divider()
SettingsSlider(
  icon = {
    Icon(
      imageVector = Icons.Default.BrightnessMedium,
      contentDescription = "Brightness Medium"
    )
  },
  title = { Text(text = "Slider") },
)
Divider()
SettingsList(
  title = { Text(text = "List") },
  subtitle = { Text(text = "Select a fruit") },
  items = listOf("Banana", "Kiwi", "Pineapple"),
  action = {
    IconButton(onClick = {  }) {
      Icon(
        imageVector = Icons.Default.Clear,
        contentDescription = "Clear",
      )
    }
  },
)

alorma/Compose-Settings: Android #JetpackCompose Settings library


UIだけでなく Preferences への読み書きも用意されています。


implementation 'com.github.alorma:compose-settings-storage-preferences:$version'

state を更新するとそのまま Preferences に書き込みされます。


val preferenceStorage = rememberPreferenceBooleanSettingState(
    key = "switch",
    defaultValue = false,
)
SettingsCheckbox(
    state = preferenceStorage, // *
    icon = {

超便利です!!

コードも良い参考にもなります。

👉 【Jetpack Compose】Icon() や Image() で ImageVector をより便利に使う hatena-bookmark


【Jetpack Compose】Icon() や Image() で ImageVector をより便利に使う

コード記述のみでベクターのマテリアルアイコン使えます。

drawable の作成が不要なので便利、変更もしやすいです。


Icon(
  imageVector = Icons.Filled.Favorite,
  contentDescription = null
)


Image(
  imageVector = Icons.Filled.Favorite,
  contentDescription = null
)

悪い点としては、

絵柄が49個しかない

絵柄を見ながら選択できない

というところでしょうか。

対応策を考えてみましょう。

 

絵柄が49個しかない

compose 公式のアイコン群(2500個以上)を追加できます。


implementation "androidx.compose.material:material-icons-extended:x.y.z"

エディタのサジェスチョンも大量に増えます。

androidx.compose.material:material-icons-extended

ただ、少し読み込みが遅い。

そこらへんは、公式に注意点があります。

警告: material-icons-extended は大規模なライブラリであり、APK のサイズに影響する可能性があります。そのため、製品版ビルドでは R8/Proguard を使用し、使用されていないリソースを取り除くことを検討してください。また、サイズが大きいために、開発中は、プロジェクトのビルド時間と Android Studio のプレビューの読み込み時間が増加する可能性があります。

👉 Compose のリソース  |  Jetpack Compose  |  Android Developers hatena-bookmark

サイズにも注意する必要があるようです。

 

絵柄を見ながら選択できない

これがすごく困ります。

別で、WEB画面を開くか、Android Studio の Vector Asset Tool を開くかして、絵柄を見て選択して、その名前から、サジェスチョンさせる、くらいしか方法がない。なんかいい方法あったら教えなさいよ。

Material Symbols and Icons - Google Fonts

👉 Material Symbols and Icons - Google Fonts hatena-bookmark

 Vector Asset Tool



将来的には、ライブプレビュー(今現在はリテラルのみ)ですばやく見れるようになるのかもしれません。

Android Studio Electric Eel 以降では、ライブ編集を使用して Compose の開発を高速化できます。ライブ編集は、リテラルのライブ編集をより強力にしたものです。この機能では、プレビューを自動的に更新し、コードの変更をエミュレータまたはデバイスにデプロイすることで、コンポーザブルの更新の影響をリアルタイムで確認できます。

 

👉 Compose のツール  |  Jetpack Compose  |  Android Developers hatena-bookmark

 

まとめ

将来性を見越して、ImageVector を使って


@Composable
fun LikeButton() {
  Button(onClick = {}) {
    Icon(
      imageVector = Icons.Filled.ThumbUp,
      contentDescription = null
    )
    Spacer(Modifier.size(ButtonDefaults.IconSpacing))
    Text("Like")
  }
}

と書きたいです!

Icons.Filled.ThumbUp

ちなみに、これまでのように ベクター drawable を作成して、id で使う記述もできます。


Icon(
  painter = painterResource(id = R.drawable.ic_baseline_favorite_24),
  contentDescription = null
)

しかし、変更時に drawable 消し忘れでゴミが溜まりそう。

あと、

Icons.Default は Icons.Filled のエイリアス

だそうです。

👉 Android Jetpack Compose Icons doesn't contain some of the material icons - Stack Overflow hatena-bookmark

👉 【Jetpack Compose】Compose Settings で数分で設定画面を作る hatena-bookmark


ViewModel はいつ生まれていつ死ぬか 【→ Jetpack Compose】

ViewModel は onCleared() を自分が破棄されるときに実行します。


public abstract class ViewModel {

    /**
     * This method will be called when this ViewModel is no longer used and will be destroyed.
     * It is useful when ViewModel observes some data and you need to clear this subscription to
     * prevent a leak of this ViewModel.
     */
    @SuppressWarnings("WeakerAccess")
    protected void onCleared() {
    }

This method will be called when this ViewModel is no longer used and will be destroyed.

👉 ViewModel の概要  |  Android デベロッパー  |  Android Developers hatena-bookmark

ログを吐かせて、その瞬間を確認します。

初期化のタイミングと合わせて確認してみましょう。


@HiltViewModel
class HomeViewModel @Inject constructor() : ViewModel() {

  // ...

  init {
    Timber.d("## ${javaClass.simpleName} initialized.")
  }

  override fun onCleared() {
    Timber.d("## ${javaClass.simpleName} onCleared.")
  }
}

👉 JakeWharton/timber: A logger with a small, extensible API which provides utility on top of Android's normal Log class. hatena-bookmark


...
21077-21077/com.example.app D/HomeViewModel: ## HomeViewModel initialized.
...
21077-21077/com.example.app D/HomeViewModel: ## HomeViewModel onCleared.
...

なんでいまさらこんなことを!

(つづく...)

👉 【Jetpack Compose】ViewModel を捨てて Repository を Composable に直結する hatena-bookmark
👉 Compose を既存のアプリ アーキテクチャと統合する  |  Jetpack Compose  |  Android Developers hatena-bookmark