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,
|
||||
* 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 colorPrimaryDark = getColor(context, R.attr.colorPrimaryDark)
|
||||
val colorAccent = getColor(context, R.attr.colorAccent)
|
||||
|
||||
@@ -34,6 +34,7 @@ android_library {
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"SystemUI-core",
|
||||
"SystemUIComposeCore",
|
||||
"SystemUIComposeFeatures",
|
||||
|
||||
|
||||
@@ -16,7 +16,40 @@
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.android.systemui.compose.gallery">
|
||||
<!-- To emulate a display size and density. -->
|
||||
<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>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.android.systemui.compose.gallery.app">
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
@@ -23,7 +24,8 @@
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.SystemUIGallery">
|
||||
android:theme="@style/Theme.SystemUI.Gallery"
|
||||
tools:replace="android:icon,android:theme,android:label">
|
||||
<activity
|
||||
android:name="com.android.systemui.compose.gallery.GalleryActivity"
|
||||
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.
|
||||
-->
|
||||
<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">
|
||||
@android:color/transparent
|
||||
</item>
|
||||
@@ -24,4 +27,4 @@
|
||||
</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
</resources>
|
||||
|
||||
@@ -9,11 +9,12 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.BrightnessHigh
|
||||
import androidx.compose.material.icons.filled.BrightnessLow
|
||||
import androidx.compose.material.icons.filled.DarkMode
|
||||
import androidx.compose.material.icons.filled.FormatSize
|
||||
import androidx.compose.material.icons.filled.FormatTextdirectionLToR
|
||||
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.Tablet
|
||||
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. */
|
||||
@Composable
|
||||
fun ConfigurationControls(
|
||||
isDarkTheme: Boolean,
|
||||
theme: Theme,
|
||||
fontScale: FontScale,
|
||||
layoutDirection: LayoutDirection,
|
||||
onChangeTheme: () -> Unit,
|
||||
onChangeLayoutDirection: () -> Unit,
|
||||
onChangeFontScale: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
// The display we are emulating, if any.
|
||||
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
|
||||
// don't miss any available configuration.
|
||||
LazyRow {
|
||||
LazyRow(modifier) {
|
||||
// Dark/light theme.
|
||||
item {
|
||||
TextButton(onChangeTheme) {
|
||||
val text: String
|
||||
val icon: ImageVector
|
||||
if (isDarkTheme) {
|
||||
icon = Icons.Default.BrightnessHigh
|
||||
text = "Dark"
|
||||
} else {
|
||||
icon = Icons.Default.BrightnessLow
|
||||
text = "Light"
|
||||
|
||||
when (theme) {
|
||||
Theme.System -> {
|
||||
icon = Icons.Default.InvertColors
|
||||
text = "System"
|
||||
}
|
||||
Theme.Dark -> {
|
||||
icon = Icons.Default.DarkMode
|
||||
text = "Dark"
|
||||
}
|
||||
Theme.Light -> {
|
||||
icon = Icons.Default.LightMode
|
||||
text = "Light"
|
||||
}
|
||||
}
|
||||
|
||||
Icon(icon, null)
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.systemui.compose.gallery
|
||||
|
||||
import android.app.UiModeManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
@@ -23,7 +25,7 @@ import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.core.view.WindowCompat
|
||||
@@ -33,22 +35,46 @@ class GalleryActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
val uiModeManager = getSystemService(Context.UI_MODE_SERVICE) as UiModeManager
|
||||
|
||||
setContent {
|
||||
val isSystemInDarkTheme = isSystemInDarkTheme()
|
||||
var isDarkTheme by remember { mutableStateOf(isSystemInDarkTheme) }
|
||||
val onChangeTheme = { isDarkTheme = !isDarkTheme }
|
||||
var theme by rememberSaveable { mutableStateOf(Theme.System) }
|
||||
val onChangeTheme = {
|
||||
// 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 useDarkIcons = !isDarkTheme
|
||||
SideEffect {
|
||||
systemUiController.setSystemBarsColor(
|
||||
color = Color.Transparent,
|
||||
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
|
||||
fun GalleryApp(
|
||||
isDarkTheme: Boolean,
|
||||
theme: Theme,
|
||||
onChangeTheme: () -> Unit,
|
||||
) {
|
||||
val systemFontScale = LocalDensity.current.fontScale
|
||||
@@ -100,14 +100,14 @@ fun GalleryApp(
|
||||
LocalDensity provides density,
|
||||
LocalLayoutDirection provides layoutDirection,
|
||||
) {
|
||||
SystemUITheme(isDarkTheme) {
|
||||
SystemUITheme {
|
||||
Surface(
|
||||
Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colorScheme.background,
|
||||
) {
|
||||
Column(Modifier.fillMaxSize().systemBarsPadding().padding(16.dp)) {
|
||||
ConfigurationControls(
|
||||
isDarkTheme,
|
||||
theme,
|
||||
fontScale,
|
||||
layoutDirection,
|
||||
onChangeTheme,
|
||||
|
||||
Reference in New Issue
Block a user