Jetpack ComposeでStatus Barの色を変更したい

この記事をシェア
JetpackCompose一問一答

Jetpack ComposeでStatus Barの色を変更するには、AccompanistのSystem UI Controllerライブラリを使います。

サンプル

ソースコードはGitHubにあります。

主な環境は以下の通りです。

  • Kotlin 1.7210
  • Compose Compiler 1.3.2
  • Compose Libraries 1.2.1
  • Material3 1.0.0-rc01
  • Accompanist 0.25.1

コンポーザブルでStatus Barの色を変更したい場面

Jetpack Composeでアプリを作っていると、以下のような理由から、Status Barの色をコンポーザブル関数内で変更したくなります。

画面遷移に合わせてStatus Barの色を変更したい

画像やビデオを表示する画面ではStatus Barを黒くする、など画面遷移に合わせてStatus Barの色を変えたい場面があります。Composeで画面遷移を実現している場合は、Status Barの色もコンポーザブル関数内から変更したくなります。

XMLのテーマを削除したい

ComposeアプリではMateral Designのテーマもコンポーザブルで設定するため、基本的にはXMLによるテーマの定義は不要になります。しかし、ComposeのテーマにはStatus Barの色を指定する機能はありません。XMLのテーマ定義を削除するには、コンポーザブル内でStatus Barの色を設定する必要があります。

依存関係の追加

まずはbuild.gradle(:app)にAccompanistライブラリの依存関係を追加します。

implementation 'com.google.accompanist:accompanist-systemuicontroller:x.x.x'

AccompanistはJetpack Composeのバージョンに対応する複数のバージョンが用意されています。最新の対応状況はAccompanistのサイトで確認してください。

色の設定

Status Barの色を設定するには、SystemUiController#setStatusBarColor()を使います。SystemUiControllerオブジェクトは、rememberSystemUiController()で取得します。

@Composable
fun StatusBarColorSample() {
    val systemUiController = rememberSystemUiController()
    SideEffect {
        systemUiController.setStatusBarColor(Color.Black)
    }
}

setStatusBarColor()は、コンポーザブル以外に影響を与える「副作用」ですので、SideEffectのスロット内に記述します。

setStatusBarColor()はどこで呼び出しても動作しますが、基本的にはひとつの画面を構成するコンポーザブル階層の一番上位のコンポーザブルに記述するのが良いと思います。アプリ内で画面によってStatus Barの色を変える場合は、各画面のコンポーザブルでそれぞれ色を指定してsetStatueBarColor()を呼び出します。

テーマカラーを指定する場合

Composeで定義したテーマカラーを取得するにはMaterialTheme.colorSchemeを参照しますが、SideEffectのスロットはコンポーザブルではないので、MaterialTheme.colorSchemeを参照できません。そこで、SideEffectの外でColorオブジェクトを取得します。

サンプルでは、ボタンを押すたびにテーマカラーのPrimary, Secondary, Tertiaryを切り替えるようにしてみました。先ほどはSideEffectスロット内でsetStatusBarColor()を呼び出しましたが、ButtonのonClick()などのイベント処理内に書くこともできます。

@Composable
fun StatusBarColorSample() {
    val systemUiController = rememberSystemUiController()
    val colors = listOf(
        MaterialTheme.colorScheme.primary,
        MaterialTheme.colorScheme.secondary,
        MaterialTheme.colorScheme.tertiary,
    )
    var colorIndex by remember { mutableStateOf(0) }

    Button(
        onClick = {
            systemUiController.setStatusBarColor(colors[colorIndex])
            colorIndex = (colorIndex + 1) % 3
        },
    ) {
        Text("Change StatusBar Color")
    }
}
JetpackCompose一問一答

Jetpack Compose一問一答

コンテンツは随時追加していきます。

この記事をシェア