Merge "Add SettingsColors & SettingsTypography"
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.settingslib.spa.framework.theme
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.staticCompositionLocalOf
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
|
||||
data class SettingsColorScheme(
|
||||
val background: Color = Color.Unspecified,
|
||||
val categoryTitle: Color = Color.Unspecified,
|
||||
val surface: Color = Color.Unspecified,
|
||||
val surfaceHeader: Color = Color.Unspecified,
|
||||
val secondaryText: Color = Color.Unspecified,
|
||||
val primaryContainer: Color = Color.Unspecified,
|
||||
val onPrimaryContainer: Color = Color.Unspecified,
|
||||
)
|
||||
|
||||
internal val LocalColorScheme = staticCompositionLocalOf { SettingsColorScheme() }
|
||||
|
||||
@Composable
|
||||
internal fun settingsColorScheme(isDarkTheme: Boolean): SettingsColorScheme {
|
||||
val context = LocalContext.current
|
||||
return remember(isDarkTheme) {
|
||||
when {
|
||||
isDarkTheme -> dynamicDarkColorScheme(context)
|
||||
else -> dynamicLightColorScheme(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a light dynamic color scheme.
|
||||
*
|
||||
* Use this function to create a color scheme based off the system wallpaper. If the developer
|
||||
* changes the wallpaper this color scheme will change accordingly. This dynamic scheme is a
|
||||
* light theme variant.
|
||||
*
|
||||
* @param context The context required to get system resource data.
|
||||
*/
|
||||
private fun dynamicLightColorScheme(context: Context): SettingsColorScheme {
|
||||
val tonalPalette = dynamicTonalPalette(context)
|
||||
return SettingsColorScheme(
|
||||
background = tonalPalette.neutral95,
|
||||
categoryTitle = tonalPalette.primary40,
|
||||
surface = tonalPalette.neutral99,
|
||||
surfaceHeader = tonalPalette.neutral90,
|
||||
secondaryText = tonalPalette.neutralVariant30,
|
||||
primaryContainer = tonalPalette.primary90,
|
||||
onPrimaryContainer = tonalPalette.neutral10,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dark dynamic color scheme.
|
||||
*
|
||||
* Use this function to create a color scheme based off the system wallpaper. If the developer
|
||||
* changes the wallpaper this color scheme will change accordingly. This dynamic scheme is a dark
|
||||
* theme variant.
|
||||
*
|
||||
* @param context The context required to get system resource data.
|
||||
*/
|
||||
private fun dynamicDarkColorScheme(context: Context): SettingsColorScheme {
|
||||
val tonalPalette = dynamicTonalPalette(context)
|
||||
return SettingsColorScheme(
|
||||
background = tonalPalette.neutral10,
|
||||
categoryTitle = tonalPalette.primary90,
|
||||
surface = tonalPalette.neutral20,
|
||||
surfaceHeader = tonalPalette.neutral30,
|
||||
secondaryText = tonalPalette.neutralVariant80,
|
||||
primaryContainer = tonalPalette.secondary90,
|
||||
onPrimaryContainer = tonalPalette.neutral10,
|
||||
)
|
||||
}
|
||||
@@ -19,6 +19,8 @@ package com.android.settingslib.spa.framework.theme
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
|
||||
/**
|
||||
* The Material 3 Theme for Settings.
|
||||
@@ -26,9 +28,21 @@ import androidx.compose.runtime.Composable
|
||||
@Composable
|
||||
fun SettingsTheme(content: @Composable () -> Unit) {
|
||||
val isDarkTheme = isSystemInDarkTheme()
|
||||
val colorScheme = materialColorScheme(isDarkTheme)
|
||||
val settingsColorScheme = settingsColorScheme(isDarkTheme)
|
||||
val colorScheme = materialColorScheme(isDarkTheme).copy(
|
||||
background = settingsColorScheme.background,
|
||||
)
|
||||
|
||||
MaterialTheme(colorScheme = colorScheme) {
|
||||
content()
|
||||
CompositionLocalProvider(LocalColorScheme provides settingsColorScheme(isDarkTheme)) {
|
||||
MaterialTheme(colorScheme = colorScheme, typography = rememberSettingsTypography()) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object SettingsTheme {
|
||||
val colorScheme: SettingsColorScheme
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = LocalColorScheme.current
|
||||
}
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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.settingslib.spa.framework.theme
|
||||
|
||||
import android.R
|
||||
import android.content.Context
|
||||
import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DoNotInline
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
/**
|
||||
* Tonal Palette structure in Material.
|
||||
*
|
||||
* A tonal palette is comprised of 5 tonal ranges. Each tonal range includes the 13 stops, or
|
||||
* tonal swatches.
|
||||
*
|
||||
* Tonal range names are:
|
||||
* - Neutral (N)
|
||||
* - Neutral variant (NV)
|
||||
* - Primary (P)
|
||||
* - Secondary (S)
|
||||
* - Tertiary (T)
|
||||
*/
|
||||
internal class SettingsTonalPalette(
|
||||
// The neutral tonal range from the generated dynamic color palette.
|
||||
// Ordered from the lightest shade [neutral100] to the darkest shade [neutral0].
|
||||
val neutral100: Color,
|
||||
val neutral99: Color,
|
||||
val neutral95: Color,
|
||||
val neutral90: Color,
|
||||
val neutral80: Color,
|
||||
val neutral70: Color,
|
||||
val neutral60: Color,
|
||||
val neutral50: Color,
|
||||
val neutral40: Color,
|
||||
val neutral30: Color,
|
||||
val neutral20: Color,
|
||||
val neutral10: Color,
|
||||
val neutral0: Color,
|
||||
|
||||
// The neutral variant tonal range, sometimes called "neutral 2", from the
|
||||
// generated dynamic color palette.
|
||||
// Ordered from the lightest shade [neutralVariant100] to the darkest shade [neutralVariant0].
|
||||
val neutralVariant100: Color,
|
||||
val neutralVariant99: Color,
|
||||
val neutralVariant95: Color,
|
||||
val neutralVariant90: Color,
|
||||
val neutralVariant80: Color,
|
||||
val neutralVariant70: Color,
|
||||
val neutralVariant60: Color,
|
||||
val neutralVariant50: Color,
|
||||
val neutralVariant40: Color,
|
||||
val neutralVariant30: Color,
|
||||
val neutralVariant20: Color,
|
||||
val neutralVariant10: Color,
|
||||
val neutralVariant0: Color,
|
||||
|
||||
// The primary tonal range from the generated dynamic color palette.
|
||||
// Ordered from the lightest shade [primary100] to the darkest shade [primary0].
|
||||
val primary100: Color,
|
||||
val primary99: Color,
|
||||
val primary95: Color,
|
||||
val primary90: Color,
|
||||
val primary80: Color,
|
||||
val primary70: Color,
|
||||
val primary60: Color,
|
||||
val primary50: Color,
|
||||
val primary40: Color,
|
||||
val primary30: Color,
|
||||
val primary20: Color,
|
||||
val primary10: Color,
|
||||
val primary0: Color,
|
||||
|
||||
// The secondary tonal range from the generated dynamic color palette.
|
||||
// Ordered from the lightest shade [secondary100] to the darkest shade [secondary0].
|
||||
val secondary100: Color,
|
||||
val secondary99: Color,
|
||||
val secondary95: Color,
|
||||
val secondary90: Color,
|
||||
val secondary80: Color,
|
||||
val secondary70: Color,
|
||||
val secondary60: Color,
|
||||
val secondary50: Color,
|
||||
val secondary40: Color,
|
||||
val secondary30: Color,
|
||||
val secondary20: Color,
|
||||
val secondary10: Color,
|
||||
val secondary0: Color,
|
||||
|
||||
// The tertiary tonal range from the generated dynamic color palette.
|
||||
// Ordered from the lightest shade [tertiary100] to the darkest shade [tertiary0].
|
||||
val tertiary100: Color,
|
||||
val tertiary99: Color,
|
||||
val tertiary95: Color,
|
||||
val tertiary90: Color,
|
||||
val tertiary80: Color,
|
||||
val tertiary70: Color,
|
||||
val tertiary60: Color,
|
||||
val tertiary50: Color,
|
||||
val tertiary40: Color,
|
||||
val tertiary30: Color,
|
||||
val tertiary20: Color,
|
||||
val tertiary10: Color,
|
||||
val tertiary0: Color,
|
||||
)
|
||||
|
||||
/** Dynamic colors in Material. */
|
||||
internal fun dynamicTonalPalette(context: Context) = SettingsTonalPalette(
|
||||
// The neutral tonal range from the generated dynamic color palette.
|
||||
neutral100 = ColorResourceHelper.getColor(context, R.color.system_neutral1_0),
|
||||
neutral99 = ColorResourceHelper.getColor(context, R.color.system_neutral1_10),
|
||||
neutral95 = ColorResourceHelper.getColor(context, R.color.system_neutral1_50),
|
||||
neutral90 = ColorResourceHelper.getColor(context, R.color.system_neutral1_100),
|
||||
neutral80 = ColorResourceHelper.getColor(context, R.color.system_neutral1_200),
|
||||
neutral70 = ColorResourceHelper.getColor(context, R.color.system_neutral1_300),
|
||||
neutral60 = ColorResourceHelper.getColor(context, R.color.system_neutral1_400),
|
||||
neutral50 = ColorResourceHelper.getColor(context, R.color.system_neutral1_500),
|
||||
neutral40 = ColorResourceHelper.getColor(context, R.color.system_neutral1_600),
|
||||
neutral30 = ColorResourceHelper.getColor(context, R.color.system_neutral1_700),
|
||||
neutral20 = ColorResourceHelper.getColor(context, R.color.system_neutral1_800),
|
||||
neutral10 = ColorResourceHelper.getColor(context, R.color.system_neutral1_900),
|
||||
neutral0 = ColorResourceHelper.getColor(context, R.color.system_neutral1_1000),
|
||||
|
||||
// The neutral variant tonal range, sometimes called "neutral 2", from the
|
||||
// generated dynamic color palette.
|
||||
neutralVariant100 = ColorResourceHelper.getColor(context, R.color.system_neutral2_0),
|
||||
neutralVariant99 = ColorResourceHelper.getColor(context, R.color.system_neutral2_10),
|
||||
neutralVariant95 = ColorResourceHelper.getColor(context, R.color.system_neutral2_50),
|
||||
neutralVariant90 = ColorResourceHelper.getColor(context, R.color.system_neutral2_100),
|
||||
neutralVariant80 = ColorResourceHelper.getColor(context, R.color.system_neutral2_200),
|
||||
neutralVariant70 = ColorResourceHelper.getColor(context, R.color.system_neutral2_300),
|
||||
neutralVariant60 = ColorResourceHelper.getColor(context, R.color.system_neutral2_400),
|
||||
neutralVariant50 = ColorResourceHelper.getColor(context, R.color.system_neutral2_500),
|
||||
neutralVariant40 = ColorResourceHelper.getColor(context, R.color.system_neutral2_600),
|
||||
neutralVariant30 = ColorResourceHelper.getColor(context, R.color.system_neutral2_700),
|
||||
neutralVariant20 = ColorResourceHelper.getColor(context, R.color.system_neutral2_800),
|
||||
neutralVariant10 = ColorResourceHelper.getColor(context, R.color.system_neutral2_900),
|
||||
neutralVariant0 = ColorResourceHelper.getColor(context, R.color.system_neutral2_1000),
|
||||
|
||||
// The primary tonal range from the generated dynamic color palette.
|
||||
primary100 = ColorResourceHelper.getColor(context, R.color.system_accent1_0),
|
||||
primary99 = ColorResourceHelper.getColor(context, R.color.system_accent1_10),
|
||||
primary95 = ColorResourceHelper.getColor(context, R.color.system_accent1_50),
|
||||
primary90 = ColorResourceHelper.getColor(context, R.color.system_accent1_100),
|
||||
primary80 = ColorResourceHelper.getColor(context, R.color.system_accent1_200),
|
||||
primary70 = ColorResourceHelper.getColor(context, R.color.system_accent1_300),
|
||||
primary60 = ColorResourceHelper.getColor(context, R.color.system_accent1_400),
|
||||
primary50 = ColorResourceHelper.getColor(context, R.color.system_accent1_500),
|
||||
primary40 = ColorResourceHelper.getColor(context, R.color.system_accent1_600),
|
||||
primary30 = ColorResourceHelper.getColor(context, R.color.system_accent1_700),
|
||||
primary20 = ColorResourceHelper.getColor(context, R.color.system_accent1_800),
|
||||
primary10 = ColorResourceHelper.getColor(context, R.color.system_accent1_900),
|
||||
primary0 = ColorResourceHelper.getColor(context, R.color.system_accent1_1000),
|
||||
|
||||
// The secondary tonal range from the generated dynamic color palette.
|
||||
secondary100 = ColorResourceHelper.getColor(context, R.color.system_accent2_0),
|
||||
secondary99 = ColorResourceHelper.getColor(context, R.color.system_accent2_10),
|
||||
secondary95 = ColorResourceHelper.getColor(context, R.color.system_accent2_50),
|
||||
secondary90 = ColorResourceHelper.getColor(context, R.color.system_accent2_100),
|
||||
secondary80 = ColorResourceHelper.getColor(context, R.color.system_accent2_200),
|
||||
secondary70 = ColorResourceHelper.getColor(context, R.color.system_accent2_300),
|
||||
secondary60 = ColorResourceHelper.getColor(context, R.color.system_accent2_400),
|
||||
secondary50 = ColorResourceHelper.getColor(context, R.color.system_accent2_500),
|
||||
secondary40 = ColorResourceHelper.getColor(context, R.color.system_accent2_600),
|
||||
secondary30 = ColorResourceHelper.getColor(context, R.color.system_accent2_700),
|
||||
secondary20 = ColorResourceHelper.getColor(context, R.color.system_accent2_800),
|
||||
secondary10 = ColorResourceHelper.getColor(context, R.color.system_accent2_900),
|
||||
secondary0 = ColorResourceHelper.getColor(context, R.color.system_accent2_1000),
|
||||
|
||||
// The tertiary tonal range from the generated dynamic color palette.
|
||||
tertiary100 = ColorResourceHelper.getColor(context, R.color.system_accent3_0),
|
||||
tertiary99 = ColorResourceHelper.getColor(context, R.color.system_accent3_10),
|
||||
tertiary95 = ColorResourceHelper.getColor(context, R.color.system_accent3_50),
|
||||
tertiary90 = ColorResourceHelper.getColor(context, R.color.system_accent3_100),
|
||||
tertiary80 = ColorResourceHelper.getColor(context, R.color.system_accent3_200),
|
||||
tertiary70 = ColorResourceHelper.getColor(context, R.color.system_accent3_300),
|
||||
tertiary60 = ColorResourceHelper.getColor(context, R.color.system_accent3_400),
|
||||
tertiary50 = ColorResourceHelper.getColor(context, R.color.system_accent3_500),
|
||||
tertiary40 = ColorResourceHelper.getColor(context, R.color.system_accent3_600),
|
||||
tertiary30 = ColorResourceHelper.getColor(context, R.color.system_accent3_700),
|
||||
tertiary20 = ColorResourceHelper.getColor(context, R.color.system_accent3_800),
|
||||
tertiary10 = ColorResourceHelper.getColor(context, R.color.system_accent3_900),
|
||||
tertiary0 = ColorResourceHelper.getColor(context, R.color.system_accent3_1000),
|
||||
)
|
||||
|
||||
private object ColorResourceHelper {
|
||||
@DoNotInline
|
||||
fun getColor(context: Context, @ColorRes id: Int): Color {
|
||||
return Color(context.resources.getColor(id, context.theme))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* 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.settingslib.spa.framework.theme
|
||||
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.em
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
private class SettingsTypography {
|
||||
private val brand = FontFamily.Default
|
||||
private val plain = FontFamily.Default
|
||||
|
||||
val typography = Typography(
|
||||
displayLarge = TextStyle(
|
||||
fontFamily = brand,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 57.sp,
|
||||
lineHeight = 64.sp,
|
||||
letterSpacing = (-0.2).sp
|
||||
),
|
||||
displayMedium = TextStyle(
|
||||
fontFamily = brand,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 45.sp,
|
||||
lineHeight = 52.sp,
|
||||
letterSpacing = 0.0.sp
|
||||
),
|
||||
displaySmall = TextStyle(
|
||||
fontFamily = brand,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 36.sp,
|
||||
lineHeight = 44.sp,
|
||||
letterSpacing = 0.0.sp
|
||||
),
|
||||
headlineLarge = TextStyle(
|
||||
fontFamily = brand,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 32.sp,
|
||||
lineHeight = 40.sp,
|
||||
letterSpacing = 0.0.sp
|
||||
),
|
||||
headlineMedium = TextStyle(
|
||||
fontFamily = brand,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 28.sp,
|
||||
lineHeight = 36.sp,
|
||||
letterSpacing = 0.0.sp
|
||||
),
|
||||
headlineSmall = TextStyle(
|
||||
fontFamily = brand,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 24.sp,
|
||||
lineHeight = 32.sp,
|
||||
letterSpacing = 0.0.sp
|
||||
),
|
||||
titleLarge = TextStyle(
|
||||
fontFamily = brand,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 22.sp,
|
||||
lineHeight = 28.sp,
|
||||
letterSpacing = 0.02.em,
|
||||
),
|
||||
titleMedium = TextStyle(
|
||||
fontFamily = brand,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 20.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = 0.02.em,
|
||||
),
|
||||
titleSmall = TextStyle(
|
||||
fontFamily = brand,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 18.sp,
|
||||
lineHeight = 20.sp,
|
||||
letterSpacing = 0.02.em,
|
||||
),
|
||||
bodyLarge = TextStyle(
|
||||
fontFamily = plain,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = 0.01.em,
|
||||
),
|
||||
bodyMedium = TextStyle(
|
||||
fontFamily = plain,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 14.sp,
|
||||
lineHeight = 20.sp,
|
||||
letterSpacing = 0.01.em,
|
||||
),
|
||||
bodySmall = TextStyle(
|
||||
fontFamily = plain,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 12.sp,
|
||||
lineHeight = 16.sp,
|
||||
letterSpacing = 0.01.em,
|
||||
),
|
||||
labelLarge = TextStyle(
|
||||
fontFamily = plain,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 16.sp,
|
||||
lineHeight = 24.sp,
|
||||
letterSpacing = 0.01.em,
|
||||
),
|
||||
labelMedium = TextStyle(
|
||||
fontFamily = plain,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 14.sp,
|
||||
lineHeight = 20.sp,
|
||||
letterSpacing = 0.01.em,
|
||||
),
|
||||
labelSmall = TextStyle(
|
||||
fontFamily = plain,
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 12.sp,
|
||||
lineHeight = 16.sp,
|
||||
letterSpacing = 0.01.em,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun rememberSettingsTypography(): Typography {
|
||||
return remember { SettingsTypography().typography }
|
||||
}
|
||||
Reference in New Issue
Block a user