はじめに
Android端末でダークテーマの切り替えをしたとき、Jetpack Composeでステータスバーカラーの切りかえをする方法を調べたので、メモ。
方法
Jetpack Composeのサンプル、Jetsnackのコードを参考にしています。
interface SystemUiController {
fun setStatusBarColor(
color: Color,
darkIcons: Boolean = color.luminance() > 0.5f
)
}
fun SystemUiController(window: Window): SystemUiController {
return SystemUiControllerImpl(window)
}
/**
* An [androidx.compose.runtime.Ambient] holding the current [SysUiController]. Defaults to a
* no-op controller; consumers should [provide][androidx.compose.runtime.Providers] a real one.
*/
val SysUiController = staticAmbientOf<SystemUiController> {
FakeSystemUiController
}
private class SystemUiControllerImpl(private val window: Window) : SystemUiController {
override fun setStatusBarColor(
color: Color,
darkIcons: Boolean
) {
window.statusBarColor = color.toArgb()
@Suppress("DEPRECATION")
if (darkIcons) {
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility or
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility and
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv()
}
}
}
private object FakeSystemUiController : SystemUiController {
override fun setStatusBarColor(color: Color, darkIcons: Boolean) = Unit
}
SystemUiController
を定義し、setStatusBarColor
でステータスバーカラーの実装をします。
アプリ全体の設定になるので、AmbientとしてSysUiController
を定義しておきます。
val SysUiController = staticAmbientOf<SystemUiController>
MainActivityのsetContentで provideし、
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
val systemUiController = remember { SystemUiController(window) }
Providers(SysUiController provides systemUiController) {
JetpackComposePlayGroundTheme {
// 省略
}
}
}
}
}
JetpackComposePlayGroundTheme
内でSysUiController.current
で SystemUiControllerを取り出し、
onCommit
でカラーが変わったら sysUiController.setStatusBarColor
を呼び出します。
@Composable
fun JetpackComposePlayGroundTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable() () -> Unit
) {
val colors = if (darkTheme) {
DarkColorPalette
} else {
LightColorPalette
}
val sysUiController = SysUiController.current
onCommit(sysUiController, colors.background) {
sysUiController.setStatusBarColor(
color = colors.background// .copy(alpha = 0.95f)
)
}
// 省略
}
下の動画のようになります。