Improve splash screen adaptive icon support

This commit is contained in:
MM20 2023-02-26 12:54:29 +01:00
parent 88bbfc41f4
commit 51aa25834e
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389

View File

@ -3,6 +3,8 @@ package de.mm20.launcher2.ui.component
import android.content.Context
import android.content.pm.PackageManager
import android.content.res.Resources
import android.graphics.drawable.AdaptiveIconDrawable
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.util.TypedValue
import androidx.compose.animation.animateColorAsState
@ -33,6 +35,9 @@ import de.mm20.launcher2.search.SavableSearchable
import de.mm20.launcher2.search.data.LauncherApp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlin.math.abs
import kotlin.math.pow
import kotlin.math.sqrt
@Composable
fun FakeSplashScreen(
@ -92,7 +97,12 @@ fun rememberSplashScreenData(searchable: SavableSearchable?): SplashScreenData {
val context = LocalContext.current
val defaultBackgroundColor = MaterialTheme.colorScheme.background
val state = remember {
mutableStateOf(SplashScreenData(backgroundColor = defaultBackgroundColor, iconSize = 288.dp))
mutableStateOf(
SplashScreenData(
backgroundColor = defaultBackgroundColor,
iconSize = 288.dp
)
)
}
LaunchedEffect(searchable) {
@ -184,7 +194,7 @@ fun rememberSplashScreenData(searchable: SavableSearchable?): SplashScreenData {
var iconSize = 288.dp
var iconBackground = if (typedValue.isColor && typedValue.data != 0) {
val iconBackground = if (typedValue.isColor && typedValue.data != 0) {
iconSize = 240.dp
Color(typedValue.data)
} else {
@ -193,7 +203,19 @@ fun rememberSplashScreenData(searchable: SavableSearchable?): SplashScreenData {
if (icon == null) {
icon = activityInfo.loadIcon(context.packageManager)
iconSize = 160.dp
iconSize = 240.dp
}
if (icon is AdaptiveIconDrawable) {
val bg = icon.background
if (bg is ColorDrawable && backgroundColor != null && iconBackground == null &&
isRgbSimilarInHsv(bg.color, backgroundColor)
) {
icon = icon.foreground
iconSize = 288.dp
} else {
iconSize = 160.dp
}
}
state.value = SplashScreenData(
@ -211,4 +233,51 @@ fun rememberSplashScreenData(searchable: SavableSearchable?): SplashScreenData {
}
internal val TypedValue.isColor
get() = type in TypedValue.TYPE_FIRST_COLOR_INT..TypedValue.TYPE_LAST_COLOR_INT
get() = type in TypedValue.TYPE_FIRST_COLOR_INT..TypedValue.TYPE_LAST_COLOR_INT
/*
* From: https://android.googlesource.com/platform/frameworks/base/+/f05f9b960832b6272b6740721c0a4bbd1ce632c1/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java#550
* Copyright (C) 2020 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.
*/
internal fun isRgbSimilarInHsv(a: Int, b: Int): Boolean {
if (a == b) {
return true
}
val lumA: Float = android.graphics.Color.luminance(a)
val lumB: Float = android.graphics.Color.luminance(b)
val contrastRatio =
if (lumA > lumB) (lumA + 0.05f) / (lumB + 0.05f) else (lumB + 0.05f) / (lumA + 0.05f)
if (contrastRatio < 2) {
return true
}
val aHsv = FloatArray(3)
val bHsv = FloatArray(3)
android.graphics.Color.colorToHSV(a, aHsv)
android.graphics.Color.colorToHSV(b, bHsv)
// Minimum degree of the hue between two colors, the result range is 0-180.
var minAngle = abs(aHsv[0] - bHsv[0]).toInt()
minAngle = (minAngle + 180) % 360 - 180
// Calculate the difference between two colors based on the HSV dimensions.
val normalizeH = minAngle / 180f
val squareH = normalizeH.toDouble().pow(2.0)
val squareS = (aHsv[1] - bHsv[1]).toDouble().pow(2.0)
val squareV = (aHsv[2] - bHsv[2]).toDouble().pow(2.0)
val square = squareH + squareS + squareV
val mean = square / 3
val root = sqrt(mean)
return root < 0.1
}