Merge "Introduce LocalAndroidColorScheme to expose Android colors"
This commit is contained in:
committed by
Android (Google) Code Review
commit
8e1cb658d0
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.android.systemui.compose.theme
|
||||
|
||||
import android.annotation.ColorInt
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.android.internal.R
|
||||
|
||||
/** CompositionLocal used to pass [AndroidColorScheme] down the tree. */
|
||||
val LocalAndroidColorScheme =
|
||||
staticCompositionLocalOf<AndroidColorScheme> {
|
||||
throw IllegalStateException(
|
||||
"No AndroidColorScheme configured. Make sure to use LocalAndroidColorScheme in a " +
|
||||
"Composable surrounded by a SystemUITheme {}."
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* The Android color scheme.
|
||||
*
|
||||
* 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) {
|
||||
val colorPrimary = getColor(context, R.attr.colorPrimary)
|
||||
val colorPrimaryDark = getColor(context, R.attr.colorPrimaryDark)
|
||||
val colorAccent = getColor(context, R.attr.colorAccent)
|
||||
val colorAccentPrimary = getColor(context, R.attr.colorAccentPrimary)
|
||||
val colorAccentSecondary = getColor(context, R.attr.colorAccentSecondary)
|
||||
val colorAccentTertiary = getColor(context, R.attr.colorAccentTertiary)
|
||||
val colorAccentPrimaryVariant = getColor(context, R.attr.colorAccentPrimaryVariant)
|
||||
val colorAccentSecondaryVariant = getColor(context, R.attr.colorAccentSecondaryVariant)
|
||||
val colorAccentTertiaryVariant = getColor(context, R.attr.colorAccentTertiaryVariant)
|
||||
val colorSurface = getColor(context, R.attr.colorSurface)
|
||||
val colorSurfaceHighlight = getColor(context, R.attr.colorSurfaceHighlight)
|
||||
val colorSurfaceVariant = getColor(context, R.attr.colorSurfaceVariant)
|
||||
val colorSurfaceHeader = getColor(context, R.attr.colorSurfaceHeader)
|
||||
val colorError = getColor(context, R.attr.colorError)
|
||||
val colorBackground = getColor(context, R.attr.colorBackground)
|
||||
val colorBackgroundFloating = getColor(context, R.attr.colorBackgroundFloating)
|
||||
val panelColorBackground = getColor(context, R.attr.panelColorBackground)
|
||||
val textColorPrimary = getColor(context, R.attr.textColorPrimary)
|
||||
val textColorSecondary = getColor(context, R.attr.textColorSecondary)
|
||||
val textColorTertiary = getColor(context, R.attr.textColorTertiary)
|
||||
val textColorPrimaryInverse = getColor(context, R.attr.textColorPrimaryInverse)
|
||||
val textColorSecondaryInverse = getColor(context, R.attr.textColorSecondaryInverse)
|
||||
val textColorTertiaryInverse = getColor(context, R.attr.textColorTertiaryInverse)
|
||||
val textColorOnAccent = getColor(context, R.attr.textColorOnAccent)
|
||||
val colorForeground = getColor(context, R.attr.colorForeground)
|
||||
val colorForegroundInverse = getColor(context, R.attr.colorForegroundInverse)
|
||||
|
||||
private fun getColor(context: Context, attr: Int): Color {
|
||||
val ta = context.obtainStyledAttributes(intArrayOf(attr))
|
||||
@ColorInt val color = ta.getColor(0, 0)
|
||||
ta.recycle()
|
||||
return Color(color)
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import androidx.compose.material3.Typography
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
|
||||
/** The Material 3 theme that should wrap all SystemUI Composables. */
|
||||
@@ -39,7 +40,14 @@ fun SystemUITheme(
|
||||
} else {
|
||||
dynamicLightColorScheme(context)
|
||||
}
|
||||
val androidColorScheme = AndroidColorScheme(context)
|
||||
val typography = Typography()
|
||||
|
||||
MaterialTheme(colorScheme, typography = typography) { content() }
|
||||
MaterialTheme(colorScheme, typography = typography) {
|
||||
CompositionLocalProvider(
|
||||
LocalAndroidColorScheme provides androidColorScheme,
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Assert.assertThrows
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -35,4 +36,22 @@ class SystemUIThemeTest {
|
||||
|
||||
composeRule.onNodeWithText("foo").assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAndroidColorsAreAvailableInsideTheme() {
|
||||
composeRule.setContent {
|
||||
SystemUITheme { Text("foo", color = LocalAndroidColorScheme.current.colorAccent) }
|
||||
}
|
||||
|
||||
composeRule.onNodeWithText("foo").assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAccessingAndroidColorsWithoutThemeThrows() {
|
||||
assertThrows(IllegalStateException::class.java) {
|
||||
composeRule.setContent {
|
||||
Text("foo", color = LocalAndroidColorScheme.current.colorAccent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
@@ -32,38 +33,88 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.android.systemui.compose.theme.LocalAndroidColorScheme
|
||||
|
||||
/** The screen that shows all the Material 3 colors. */
|
||||
@Composable
|
||||
fun ColorsScreen() {
|
||||
fun MaterialColorsScreen() {
|
||||
val colors = MaterialTheme.colorScheme
|
||||
LazyColumn {
|
||||
item { ColorTile(colors.primary, "primary") }
|
||||
item { ColorTile(colors.onPrimary, "onPrimary") }
|
||||
item { ColorTile(colors.primaryContainer, "primaryContainer") }
|
||||
item { ColorTile(colors.onPrimaryContainer, "onPrimaryContainer") }
|
||||
item { ColorTile(colors.inversePrimary, "inversePrimary") }
|
||||
item { ColorTile(colors.secondary, "secondary") }
|
||||
item { ColorTile(colors.onSecondary, "onSecondary") }
|
||||
item { ColorTile(colors.secondaryContainer, "secondaryContainer") }
|
||||
item { ColorTile(colors.onSecondaryContainer, "onSecondaryContainer") }
|
||||
item { ColorTile(colors.tertiary, "tertiary") }
|
||||
item { ColorTile(colors.onTertiary, "onTertiary") }
|
||||
item { ColorTile(colors.tertiaryContainer, "tertiaryContainer") }
|
||||
item { ColorTile(colors.onTertiaryContainer, "onTertiaryContainer") }
|
||||
item { ColorTile(colors.background, "background") }
|
||||
item { ColorTile(colors.onBackground, "onBackground") }
|
||||
item { ColorTile(colors.surface, "surface") }
|
||||
item { ColorTile(colors.onSurface, "onSurface") }
|
||||
item { ColorTile(colors.surfaceVariant, "surfaceVariant") }
|
||||
item { ColorTile(colors.onSurfaceVariant, "onSurfaceVariant") }
|
||||
item { ColorTile(colors.inverseSurface, "inverseSurface") }
|
||||
item { ColorTile(colors.inverseOnSurface, "inverseOnSurface") }
|
||||
item { ColorTile(colors.error, "error") }
|
||||
item { ColorTile(colors.onError, "onError") }
|
||||
item { ColorTile(colors.errorContainer, "errorContainer") }
|
||||
item { ColorTile(colors.onErrorContainer, "onErrorContainer") }
|
||||
item { ColorTile(colors.outline, "outline") }
|
||||
ColorsScreen(
|
||||
listOf(
|
||||
"primary" to colors.primary,
|
||||
"onPrimary" to colors.onPrimary,
|
||||
"primaryContainer" to colors.primaryContainer,
|
||||
"onPrimaryContainer" to colors.onPrimaryContainer,
|
||||
"inversePrimary" to colors.inversePrimary,
|
||||
"secondary" to colors.secondary,
|
||||
"onSecondary" to colors.onSecondary,
|
||||
"secondaryContainer" to colors.secondaryContainer,
|
||||
"onSecondaryContainer" to colors.onSecondaryContainer,
|
||||
"tertiary" to colors.tertiary,
|
||||
"onTertiary" to colors.onTertiary,
|
||||
"tertiaryContainer" to colors.tertiaryContainer,
|
||||
"onTertiaryContainer" to colors.onTertiaryContainer,
|
||||
"background" to colors.background,
|
||||
"onBackground" to colors.onBackground,
|
||||
"surface" to colors.surface,
|
||||
"onSurface" to colors.onSurface,
|
||||
"surfaceVariant" to colors.surfaceVariant,
|
||||
"onSurfaceVariant" to colors.onSurfaceVariant,
|
||||
"inverseSurface" to colors.inverseSurface,
|
||||
"inverseOnSurface" to colors.inverseOnSurface,
|
||||
"error" to colors.error,
|
||||
"onError" to colors.onError,
|
||||
"errorContainer" to colors.errorContainer,
|
||||
"onErrorContainer" to colors.onErrorContainer,
|
||||
"outline" to colors.outline,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** The screen that shows all the Android colors. */
|
||||
@Composable
|
||||
fun AndroidColorsScreen() {
|
||||
val colors = LocalAndroidColorScheme.current
|
||||
ColorsScreen(
|
||||
listOf(
|
||||
"colorPrimary" to colors.colorPrimary,
|
||||
"colorPrimaryDark" to colors.colorPrimaryDark,
|
||||
"colorAccent" to colors.colorAccent,
|
||||
"colorAccentPrimary" to colors.colorAccentPrimary,
|
||||
"colorAccentSecondary" to colors.colorAccentSecondary,
|
||||
"colorAccentTertiary" to colors.colorAccentTertiary,
|
||||
"colorAccentPrimaryVariant" to colors.colorAccentPrimaryVariant,
|
||||
"colorAccentSecondaryVariant" to colors.colorAccentSecondaryVariant,
|
||||
"colorAccentTertiaryVariant" to colors.colorAccentTertiaryVariant,
|
||||
"colorSurface" to colors.colorSurface,
|
||||
"colorSurfaceHighlight" to colors.colorSurfaceHighlight,
|
||||
"colorSurfaceVariant" to colors.colorSurfaceVariant,
|
||||
"colorSurfaceHeader" to colors.colorSurfaceHeader,
|
||||
"colorError" to colors.colorError,
|
||||
"colorBackground" to colors.colorBackground,
|
||||
"colorBackgroundFloating" to colors.colorBackgroundFloating,
|
||||
"panelColorBackground" to colors.panelColorBackground,
|
||||
"textColorPrimary" to colors.textColorPrimary,
|
||||
"textColorSecondary" to colors.textColorSecondary,
|
||||
"textColorTertiary" to colors.textColorTertiary,
|
||||
"textColorPrimaryInverse" to colors.textColorPrimaryInverse,
|
||||
"textColorSecondaryInverse" to colors.textColorSecondaryInverse,
|
||||
"textColorTertiaryInverse" to colors.textColorTertiaryInverse,
|
||||
"textColorOnAccent" to colors.textColorOnAccent,
|
||||
"colorForeground" to colors.colorForeground,
|
||||
"colorForegroundInverse" to colors.colorForegroundInverse,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ColorsScreen(
|
||||
colors: List<Pair<String, Color>>,
|
||||
) {
|
||||
LazyColumn(
|
||||
Modifier.fillMaxWidth(),
|
||||
) {
|
||||
colors.forEach { (name, color) -> item { ColorTile(color, name) } }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,8 @@ import com.android.systemui.compose.theme.SystemUITheme
|
||||
enum class Screen {
|
||||
Home,
|
||||
Typography,
|
||||
Colors,
|
||||
MaterialColors,
|
||||
AndroidColors,
|
||||
ExampleFeature,
|
||||
}
|
||||
|
||||
@@ -49,7 +50,8 @@ private fun MainContent() {
|
||||
)
|
||||
}
|
||||
composable(Screen.Typography.name) { TypographyScreen() }
|
||||
composable(Screen.Colors.name) { ColorsScreen() }
|
||||
composable(Screen.MaterialColors.name) { MaterialColorsScreen() }
|
||||
composable(Screen.AndroidColors.name) { AndroidColorsScreen() }
|
||||
composable(Screen.ExampleFeature.name) { ExampleFeatureScreen() }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user