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_screen_colors">Color scheme</string>
<string name="preference_colors_default">Default</string> <string name="preference_colors_default">Default</string>
<string name="preference_colors_bw">Black and White</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_screen_about">About</string>
<string name="preference_version">Version</string> <string name="preference_version">Version</string>
<string name="preference_category_links">Links</string> <string name="preference_category_links">Links</string>

View File

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

View File

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

View File

@ -1,8 +1,5 @@
package de.mm20.launcher2.ui.settings.colorscheme 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.foundation.layout.*
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.RadioButtonChecked 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.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.ktx.isAtLeastApiLevel
import de.mm20.launcher2.preferences.Settings.AppearanceSettings import de.mm20.launcher2.preferences.Settings.AppearanceSettings
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.preferences.Preference import de.mm20.launcher2.ui.component.preferences.Preference
@ -41,12 +36,6 @@ fun ColorSchemeSettingsScreen() {
AppearanceSettings.ColorScheme.BlackAndWhite to R.string.preference_colors_bw, 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) { for (cs in items) {
val scheme by colorSchemeAsState(cs.first) val scheme by colorSchemeAsState(cs.first)
Preference( Preference(

View File

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

View File

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

View File

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

View File

@ -7,63 +7,41 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.graphics.toArgb
import de.mm20.launcher2.ui.theme.WallpaperColors import de.mm20.launcher2.ui.theme.WallpaperColors
import palettes.TonalPalette import palettes.TonalPalette
import scheme.Scheme
fun WallpaperColorScheme(wallpaperColors: WallpaperColors, darkTheme: Boolean): ColorScheme { fun MaterialYouCompatScheme(wallpaperColors: WallpaperColors, darkTheme: Boolean): ColorScheme {
val primary = TonalPalette.fromInt(wallpaperColors.primary.toArgb()) val scheme = if (darkTheme) {
val secondary = TonalPalette.fromInt((wallpaperColors.secondary ?: wallpaperColors.primary).toArgb()) Scheme.dark(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)),
)
} else { } else {
lightColorScheme( Scheme.light(wallpaperColors.primary.toArgb())
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)),)
} }
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),
)
} }