Force the app dark/light theme in the Gallery app (1/2)
Before this CL, the Gallery app would use a boolean isDarkTheme that would be toggled and passed to the SystemUITheme to force set the dark/light theme of the app. However, this does not work for Views and the AndroidColors, for which we need to set the app dark/light theme using UiModeManager. Bug: 238993727 Test: Builds Change-Id: Ic3efb42d371c6aac8c2a6297a0cb192a780903cd
This commit is contained in:
@@ -37,7 +37,7 @@ val LocalAndroidColorScheme =
|
|||||||
* Important: Use M3 colors from MaterialTheme.colorScheme whenever possible instead. In the future,
|
* Important: Use M3 colors from MaterialTheme.colorScheme whenever possible instead. In the future,
|
||||||
* most of the colors in this class will be removed in favor of their M3 counterpart.
|
* most of the colors in this class will be removed in favor of their M3 counterpart.
|
||||||
*/
|
*/
|
||||||
class AndroidColorScheme internal constructor(private val context: Context) {
|
class AndroidColorScheme internal constructor(context: Context) {
|
||||||
val colorPrimary = getColor(context, R.attr.colorPrimary)
|
val colorPrimary = getColor(context, R.attr.colorPrimary)
|
||||||
val colorPrimaryDark = getColor(context, R.attr.colorPrimaryDark)
|
val colorPrimaryDark = getColor(context, R.attr.colorPrimaryDark)
|
||||||
val colorAccent = getColor(context, R.attr.colorAccent)
|
val colorAccent = getColor(context, R.attr.colorAccent)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ android_library {
|
|||||||
],
|
],
|
||||||
|
|
||||||
static_libs: [
|
static_libs: [
|
||||||
|
"SystemUI-core",
|
||||||
"SystemUIComposeCore",
|
"SystemUIComposeCore",
|
||||||
"SystemUIComposeFeatures",
|
"SystemUIComposeFeatures",
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,40 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.android.systemui.compose.gallery">
|
package="com.android.systemui.compose.gallery">
|
||||||
<!-- To emulate a display size and density. -->
|
<!-- To emulate a display size and density. -->
|
||||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
|
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name="android.app.Application"
|
||||||
|
android:appComponentFactory="androidx.core.app.AppComponentFactory"
|
||||||
|
tools:replace="android:name,android:appComponentFactory">
|
||||||
|
<!-- Disable providers from SystemUI -->
|
||||||
|
<provider android:name="com.android.systemui.keyguard.KeyguardSliceProvider"
|
||||||
|
android:authorities="com.android.systemui.test.keyguard.disabled"
|
||||||
|
android:enabled="false"
|
||||||
|
tools:replace="android:authorities"
|
||||||
|
tools:node="remove" />
|
||||||
|
<provider android:name="com.google.android.systemui.keyguard.KeyguardSliceProviderGoogle"
|
||||||
|
android:authorities="com.android.systemui.test.keyguard.disabled"
|
||||||
|
android:enabled="false"
|
||||||
|
tools:replace="android:authorities"
|
||||||
|
tools:node="remove" />
|
||||||
|
<provider android:name="com.android.keyguard.clock.ClockOptionsProvider"
|
||||||
|
android:authorities="com.android.systemui.test.keyguard.clock.disabled"
|
||||||
|
android:enabled="false"
|
||||||
|
tools:replace="android:authorities"
|
||||||
|
tools:node="remove" />
|
||||||
|
<provider android:name="com.android.systemui.people.PeopleProvider"
|
||||||
|
android:authorities="com.android.systemui.test.people.disabled"
|
||||||
|
android:enabled="false"
|
||||||
|
tools:replace="android:authorities"
|
||||||
|
tools:node="remove" />
|
||||||
|
<provider android:name="androidx.core.content.FileProvider"
|
||||||
|
android:authorities="com.android.systemui.test.fileprovider.disabled"
|
||||||
|
android:enabled="false"
|
||||||
|
tools:replace="android:authorities"
|
||||||
|
tools:node="remove"/>
|
||||||
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="com.android.systemui.compose.gallery.app">
|
package="com.android.systemui.compose.gallery.app">
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
@@ -23,7 +24,8 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.SystemUIGallery">
|
android:theme="@style/Theme.SystemUI.Gallery"
|
||||||
|
tools:replace="android:icon,android:theme,android:label">
|
||||||
<activity
|
<activity
|
||||||
android:name="com.android.systemui.compose.gallery.GalleryActivity"
|
android:name="com.android.systemui.compose.gallery.GalleryActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
Copyright (C) 2022 The Android Open Source Project
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
-->
|
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
<style name="Theme.SystemUIGallery" parent="Theme.AppCompat.DayNight.NoActionBar">
|
|
||||||
<item name="android:statusBarColor" tools:targetApi="l">
|
|
||||||
@android:color/transparent
|
|
||||||
</item>
|
|
||||||
<item name="android:navigationBarColor" tools:targetApi="l">
|
|
||||||
@android:color/transparent
|
|
||||||
</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
|
||||||
@@ -15,7 +15,10 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<style name="Theme.SystemUIGallery" parent="Theme.AppCompat.DayNight.NoActionBar">
|
<style name="Theme.SystemUI.Gallery">
|
||||||
|
<item name="android:windowActionBar">false</item>
|
||||||
|
<item name="android:windowNoTitle">true</item>
|
||||||
|
|
||||||
<item name="android:statusBarColor" tools:targetApi="l">
|
<item name="android:statusBarColor" tools:targetApi="l">
|
||||||
@android:color/transparent
|
@android:color/transparent
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ import androidx.compose.foundation.layout.Spacer
|
|||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.BrightnessHigh
|
import androidx.compose.material.icons.filled.DarkMode
|
||||||
import androidx.compose.material.icons.filled.BrightnessLow
|
|
||||||
import androidx.compose.material.icons.filled.FormatSize
|
import androidx.compose.material.icons.filled.FormatSize
|
||||||
import androidx.compose.material.icons.filled.FormatTextdirectionLToR
|
import androidx.compose.material.icons.filled.FormatTextdirectionLToR
|
||||||
import androidx.compose.material.icons.filled.FormatTextdirectionRToL
|
import androidx.compose.material.icons.filled.FormatTextdirectionRToL
|
||||||
|
import androidx.compose.material.icons.filled.InvertColors
|
||||||
|
import androidx.compose.material.icons.filled.LightMode
|
||||||
import androidx.compose.material.icons.filled.Smartphone
|
import androidx.compose.material.icons.filled.Smartphone
|
||||||
import androidx.compose.material.icons.filled.Tablet
|
import androidx.compose.material.icons.filled.Tablet
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
@@ -44,12 +45,13 @@ enum class FontScale(val scale: Float) {
|
|||||||
/** A configuration panel that allows to toggle the theme, font scale and layout direction. */
|
/** A configuration panel that allows to toggle the theme, font scale and layout direction. */
|
||||||
@Composable
|
@Composable
|
||||||
fun ConfigurationControls(
|
fun ConfigurationControls(
|
||||||
isDarkTheme: Boolean,
|
theme: Theme,
|
||||||
fontScale: FontScale,
|
fontScale: FontScale,
|
||||||
layoutDirection: LayoutDirection,
|
layoutDirection: LayoutDirection,
|
||||||
onChangeTheme: () -> Unit,
|
onChangeTheme: () -> Unit,
|
||||||
onChangeLayoutDirection: () -> Unit,
|
onChangeLayoutDirection: () -> Unit,
|
||||||
onChangeFontScale: () -> Unit,
|
onChangeFontScale: () -> Unit,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
// The display we are emulating, if any.
|
// The display we are emulating, if any.
|
||||||
var emulatedDisplayName by rememberSaveable { mutableStateOf<String?>(null) }
|
var emulatedDisplayName by rememberSaveable { mutableStateOf<String?>(null) }
|
||||||
@@ -84,18 +86,26 @@ fun ConfigurationControls(
|
|||||||
|
|
||||||
// TODO(b/231131244): Fork FlowRow from Accompanist and use that instead to make sure that users
|
// TODO(b/231131244): Fork FlowRow from Accompanist and use that instead to make sure that users
|
||||||
// don't miss any available configuration.
|
// don't miss any available configuration.
|
||||||
LazyRow {
|
LazyRow(modifier) {
|
||||||
// Dark/light theme.
|
// Dark/light theme.
|
||||||
item {
|
item {
|
||||||
TextButton(onChangeTheme) {
|
TextButton(onChangeTheme) {
|
||||||
val text: String
|
val text: String
|
||||||
val icon: ImageVector
|
val icon: ImageVector
|
||||||
if (isDarkTheme) {
|
|
||||||
icon = Icons.Default.BrightnessHigh
|
when (theme) {
|
||||||
text = "Dark"
|
Theme.System -> {
|
||||||
} else {
|
icon = Icons.Default.InvertColors
|
||||||
icon = Icons.Default.BrightnessLow
|
text = "System"
|
||||||
text = "Light"
|
}
|
||||||
|
Theme.Dark -> {
|
||||||
|
icon = Icons.Default.DarkMode
|
||||||
|
text = "Dark"
|
||||||
|
}
|
||||||
|
Theme.Light -> {
|
||||||
|
icon = Icons.Default.LightMode
|
||||||
|
text = "Light"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Icon(icon, null)
|
Icon(icon, null)
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.systemui.compose.gallery
|
package com.android.systemui.compose.gallery
|
||||||
|
|
||||||
|
import android.app.UiModeManager
|
||||||
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
@@ -23,7 +25,7 @@ import androidx.compose.foundation.isSystemInDarkTheme
|
|||||||
import androidx.compose.runtime.SideEffect
|
import androidx.compose.runtime.SideEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
@@ -33,22 +35,46 @@ class GalleryActivity : ComponentActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||||
|
val uiModeManager = getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
val isSystemInDarkTheme = isSystemInDarkTheme()
|
var theme by rememberSaveable { mutableStateOf(Theme.System) }
|
||||||
var isDarkTheme by remember { mutableStateOf(isSystemInDarkTheme) }
|
val onChangeTheme = {
|
||||||
val onChangeTheme = { isDarkTheme = !isDarkTheme }
|
// Change to the next theme for a toggle behavior.
|
||||||
|
theme =
|
||||||
|
when (theme) {
|
||||||
|
Theme.System -> Theme.Dark
|
||||||
|
Theme.Dark -> Theme.Light
|
||||||
|
Theme.Light -> Theme.System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val isSystemInDarkTheme = isSystemInDarkTheme()
|
||||||
|
val isDark = theme == Theme.Dark || (theme == Theme.System && isSystemInDarkTheme)
|
||||||
|
val useDarkIcons = !isDark
|
||||||
val systemUiController = rememberSystemUiController()
|
val systemUiController = rememberSystemUiController()
|
||||||
val useDarkIcons = !isDarkTheme
|
|
||||||
SideEffect {
|
SideEffect {
|
||||||
systemUiController.setSystemBarsColor(
|
systemUiController.setSystemBarsColor(
|
||||||
color = Color.Transparent,
|
color = Color.Transparent,
|
||||||
darkIcons = useDarkIcons,
|
darkIcons = useDarkIcons,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
uiModeManager.setApplicationNightMode(
|
||||||
|
when (theme) {
|
||||||
|
Theme.System -> UiModeManager.MODE_NIGHT_AUTO
|
||||||
|
Theme.Dark -> UiModeManager.MODE_NIGHT_YES
|
||||||
|
Theme.Light -> UiModeManager.MODE_NIGHT_NO
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
GalleryApp(isDarkTheme, onChangeTheme)
|
GalleryApp(theme, onChangeTheme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class Theme {
|
||||||
|
System,
|
||||||
|
Dark,
|
||||||
|
Light,
|
||||||
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ private fun MainContent() {
|
|||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun GalleryApp(
|
fun GalleryApp(
|
||||||
isDarkTheme: Boolean,
|
theme: Theme,
|
||||||
onChangeTheme: () -> Unit,
|
onChangeTheme: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val systemFontScale = LocalDensity.current.fontScale
|
val systemFontScale = LocalDensity.current.fontScale
|
||||||
@@ -100,14 +100,14 @@ fun GalleryApp(
|
|||||||
LocalDensity provides density,
|
LocalDensity provides density,
|
||||||
LocalLayoutDirection provides layoutDirection,
|
LocalLayoutDirection provides layoutDirection,
|
||||||
) {
|
) {
|
||||||
SystemUITheme(isDarkTheme) {
|
SystemUITheme {
|
||||||
Surface(
|
Surface(
|
||||||
Modifier.fillMaxSize(),
|
Modifier.fillMaxSize(),
|
||||||
color = MaterialTheme.colorScheme.background,
|
color = MaterialTheme.colorScheme.background,
|
||||||
) {
|
) {
|
||||||
Column(Modifier.fillMaxSize().systemBarsPadding().padding(16.dp)) {
|
Column(Modifier.fillMaxSize().systemBarsPadding().padding(16.dp)) {
|
||||||
ConfigurationControls(
|
ConfigurationControls(
|
||||||
isDarkTheme,
|
theme,
|
||||||
fontScale,
|
fontScale,
|
||||||
layoutDirection,
|
layoutDirection,
|
||||||
onChangeTheme,
|
onChangeTheme,
|
||||||
|
|||||||
Reference in New Issue
Block a user