Transform wallpaper color scheme into Material You compat color scheme on Android 8.1 – 11

and make it the default on these platforms
This commit is contained in:
MM20 2022-04-12 19:25:17 +02:00
parent 8bb3737460
commit f2041e51c2
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
8 changed files with 70 additions and 99 deletions

View File

@ -387,7 +387,6 @@
<string name="preference_screen_colors">Color scheme</string>
<string name="preference_colors_default">Default</string>
<string name="preference_colors_bw">Black and White</string>
<string name="preference_colors_wallpaper">From wallpaper</string>
<string name="preference_screen_about">About</string>
<string name="preference_version">Version</string>
<string name="preference_category_links">Links</string>

View File

@ -15,7 +15,6 @@ message Settings {
enum ColorScheme {
Default = 0;
BlackAndWhite = 1;
Wallpaper = 2;
}
ColorScheme color_scheme = 6;
bool dim_wallpaper = 7;

View File

@ -71,7 +71,6 @@ fun AppearanceSettingsScreen() {
summary = when (colorScheme) {
ColorScheme.Default -> stringResource(R.string.preference_colors_default)
ColorScheme.BlackAndWhite -> stringResource(R.string.preference_colors_bw)
ColorScheme.Wallpaper -> stringResource(R.string.preference_colors_wallpaper)
else -> null
},
onClick = {

View File

@ -1,8 +1,5 @@
package de.mm20.launcher2.ui.settings.colorscheme
import android.os.Build
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.RadioButtonChecked
@ -15,11 +12,9 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.ktx.isAtLeastApiLevel
import de.mm20.launcher2.preferences.Settings.AppearanceSettings
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.preferences.Preference
@ -41,12 +36,6 @@ fun ColorSchemeSettingsScreen() {
AppearanceSettings.ColorScheme.BlackAndWhite to R.string.preference_colors_bw,
)
if (isAtLeastApiLevel(Build.VERSION_CODES.O_MR1)) {
items.add(
AppearanceSettings.ColorScheme.Wallpaper to R.string.preference_colors_wallpaper
)
}
for (cs in items) {
val scheme by colorSchemeAsState(cs.first)
Preference(

View File

@ -8,7 +8,6 @@ import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalContext
import de.mm20.launcher2.ktx.isAtLeastApiLevel
import de.mm20.launcher2.preferences.LauncherDataStore
import de.mm20.launcher2.preferences.Settings.AppearanceSettings
import de.mm20.launcher2.preferences.Settings.AppearanceSettings.Theme
@ -49,31 +48,38 @@ fun colorSchemeAsState(colorScheme: AppearanceSettings.ColorScheme): MutableStat
val darkTheme =
themePreference == Theme.Dark || themePreference == Theme.System && isSystemInDarkTheme()
val state = remember(colorScheme, darkTheme) {
mutableStateOf(
when (colorScheme) {
AppearanceSettings.ColorScheme.BlackAndWhite -> {
when (colorScheme) {
AppearanceSettings.ColorScheme.BlackAndWhite -> {
return remember(darkTheme) {
mutableStateOf(
if (darkTheme) DarkBlackAndWhiteColorScheme else LightBlackAndWhiteColorScheme
}
else -> {
if (darkTheme) {
if (isAtLeastApiLevel(31)) dynamicDarkColorScheme(context)
else DarkPre31DefaultColorScheme
} else {
if (isAtLeastApiLevel(31)) dynamicLightColorScheme(context)
else LightPre31DefaultColorScheme
}
)
}
}
else -> {
if (Build.VERSION.SDK_INT >= 31) {
return remember(darkTheme) {
mutableStateOf(
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
)
}
}
)
}
if (colorScheme == AppearanceSettings.ColorScheme.Wallpaper && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
val wallpaperColors by wallpaperColorsAsState()
LaunchedEffect(wallpaperColors, darkTheme) {
state.value = WallpaperColorScheme(wallpaperColors, darkTheme)
if (Build.VERSION.SDK_INT >= 27 && Build.VERSION.SDK_INT < 31) {
val wallpaperColors by wallpaperColorsAsState()
val state = remember(wallpaperColors, darkTheme) {
mutableStateOf(
wallpaperColors?.let { MaterialYouCompatScheme(it, darkTheme) }
?: if (darkTheme) DarkDefaultColorScheme else LightDefaultColorScheme
)
}
return state
}
return remember { mutableStateOf(if (darkTheme) DarkDefaultColorScheme else LightDefaultColorScheme) }
}
}
return state
}

View File

@ -4,13 +4,11 @@ import android.app.WallpaperManager
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.compose.runtime.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@ -29,15 +27,18 @@ data class WallpaperColors(val primary: Color, val secondary: Color?, val tertia
@RequiresApi(Build.VERSION_CODES.O_MR1)
@Composable
fun wallpaperColorsAsState(): State<WallpaperColors> {
fun wallpaperColorsAsState(): State<WallpaperColors?> {
val scope = rememberCoroutineScope()
val context = LocalContext.current
val state = remember { mutableStateOf(DefaultWallpaperColors) }
val state = remember { mutableStateOf<WallpaperColors?>(null) }
DisposableEffect(null) {
val wallpaperManager = WallpaperManager.getInstance(context)
val callback = { colors: android.app.WallpaperColors?, which: Int ->
if (colors != null && which or WallpaperManager.FLAG_SYSTEM != 0) {
val callback = callback@{ colors: android.app.WallpaperColors?, which: Int ->
if (which or WallpaperManager.FLAG_SYSTEM == 0) return@callback
if (colors != null) {
state.value = WallpaperColors.fromPlatformType(colors)
} else {
state.value = null
}
}
wallpaperManager.addOnColorsChangedListener(

View File

@ -4,7 +4,7 @@ import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
val LightPre31DefaultColorScheme = lightColorScheme(
val LightDefaultColorScheme = lightColorScheme(
primary = Color(0xFF3C6089),
onPrimary = Color(0xFFFFFFFF),
primaryContainer = Color(0xFFD1E4FF),
@ -33,7 +33,7 @@ val LightPre31DefaultColorScheme = lightColorScheme(
outline = Color(0xFF6D778C),
)
val DarkPre31DefaultColorScheme = darkColorScheme(
val DarkDefaultColorScheme = darkColorScheme(
primary = Color(0xFFA6C9F8),
onPrimary = Color(0xFF033259),
primaryContainer = Color(0xFF234870),

View File

@ -7,63 +7,41 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import de.mm20.launcher2.ui.theme.WallpaperColors
import palettes.TonalPalette
import scheme.Scheme
fun WallpaperColorScheme(wallpaperColors: WallpaperColors, darkTheme: Boolean): ColorScheme {
val primary = TonalPalette.fromInt(wallpaperColors.primary.toArgb())
val secondary = TonalPalette.fromInt((wallpaperColors.secondary ?: wallpaperColors.primary).toArgb())
val tertiary = TonalPalette.fromInt((wallpaperColors.tertiary ?: wallpaperColors.primary).toArgb())
val neutral1 = TonalPalette.fromInt(Color.Black.toArgb())
val neutral2 = TonalPalette.fromInt(Color.Black.toArgb())
return if(darkTheme) {
darkColorScheme(
primary = Color(primary.tone(80)),
onPrimary = Color(primary.tone(20)),
primaryContainer = Color(primary.tone(30)),
onPrimaryContainer = Color(primary.tone(90)),
secondary = Color(secondary.tone(80)),
onSecondary = Color(secondary.tone(20)),
secondaryContainer = Color(secondary.tone(30)),
onSecondaryContainer = Color(secondary.tone(90)),
tertiary = Color(tertiary.tone(80)),
onTertiary = Color(tertiary.tone(20)),
tertiaryContainer = Color(tertiary.tone(30)),
onTertiaryContainer = Color(tertiary.tone(90)),
background = Color(neutral1.tone(10)),
onBackground = Color(neutral1.tone(90)),
surface = Color(neutral1.tone(10)),
onSurface = Color(neutral1.tone(90)),
surfaceVariant = Color(neutral2.tone(30)),
onSurfaceVariant = Color(neutral2.tone(80)),
outline = Color(neutral2.tone(60)),
inverseSurface = Color(neutral1.tone(90)),
inverseOnSurface = Color(neutral1.tone(20)),
inversePrimary = Color(primary.tone(40)),
)
fun MaterialYouCompatScheme(wallpaperColors: WallpaperColors, darkTheme: Boolean): ColorScheme {
val scheme = if (darkTheme) {
Scheme.dark(wallpaperColors.primary.toArgb())
} else {
lightColorScheme(
primary = Color(primary.tone(40)),
onPrimary = Color(primary.tone(100)),
primaryContainer = Color(primary.tone(90)),
onPrimaryContainer = Color(primary.tone(10)),
secondary = Color(secondary.tone(40)),
onSecondary = Color(secondary.tone(100)),
secondaryContainer = Color(secondary.tone(90)),
onSecondaryContainer = Color(secondary.tone(10)),
tertiary = Color(tertiary.tone(40)),
onTertiary = Color(tertiary.tone(100)),
tertiaryContainer = Color(tertiary.tone(90)),
onTertiaryContainer = Color(tertiary.tone(10)),
background = Color(neutral1.tone(99)),
onBackground = Color(neutral1.tone(10)),
surface = Color(neutral1.tone(99)),
onSurface = Color(neutral1.tone(10)),
surfaceVariant = Color(neutral2.tone(90)),
onSurfaceVariant = Color(neutral2.tone(30)),
outline = Color(neutral2.tone(50)),
inverseSurface = Color(neutral1.tone(20)),
inverseOnSurface = Color(neutral1.tone(95)),
inversePrimary = Color(primary.tone(80)),)
Scheme.light(wallpaperColors.primary.toArgb())
}
return ColorScheme(
primary = Color(scheme.primary),
onPrimary = Color(scheme.onPrimary),
primaryContainer = Color(scheme.primaryContainer),
onPrimaryContainer = Color(scheme.onPrimaryContainer),
secondary = Color(scheme.secondary),
onSecondary = Color(scheme.onSecondary),
secondaryContainer = Color(scheme.secondaryContainer),
onSecondaryContainer = Color(scheme.onSecondaryContainer),
tertiary = Color(scheme.tertiary),
onTertiary = Color(scheme.onTertiary),
tertiaryContainer = Color(scheme.tertiaryContainer),
onTertiaryContainer = Color(scheme.onTertiaryContainer),
background = Color(scheme.background),
onBackground = Color(scheme.onBackground),
surface = Color(scheme.surface),
onSurface = Color(scheme.onSurface),
surfaceVariant = Color(scheme.surfaceVariant),
onSurfaceVariant = Color(scheme.onSurfaceVariant),
outline = Color(scheme.outline),
inverseSurface = Color(scheme.inverseSurface),
inverseOnSurface = Color(scheme.inverseOnSurface),
inversePrimary = Color(scheme.inversePrimary),
surfaceTint = Color(scheme.primary),
error = Color(scheme.error),
onError = Color(scheme.onError),
errorContainer = Color(scheme.errorContainer),
onErrorContainer = Color(scheme.onErrorContainer),
)
}