Fake splash screen: add support for legacy splash screens

This commit is contained in:
MM20 2023-02-26 01:04:57 +01:00
parent 608d73706a
commit 88bbfc41f4
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389

View File

@ -1,6 +1,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.Drawable
import android.util.TypedValue
import androidx.compose.animation.animateColorAsState
@ -10,6 +12,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
@ -21,6 +24,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import coil.compose.AsyncImage
@ -49,8 +53,16 @@ fun FakeSplashScreen(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
if (splashScreenData.iconBackground != null) {
Surface(
modifier = Modifier.size(192.dp),
shape = CircleShape,
color = splashScreenData.iconBackground
) {
}
}
AsyncImage(
modifier = Modifier.size(288.dp),
modifier = Modifier.size(splashScreenData.iconSize),
model = splashScreenData.icon,
contentDescription = null
)
@ -70,6 +82,7 @@ fun FakeSplashScreen(
data class SplashScreenData(
val backgroundColor: Color,
val icon: Drawable? = null,
val iconSize: Dp,
val brandingIcon: Drawable? = null,
val iconBackground: Color? = null,
)
@ -79,13 +92,24 @@ fun rememberSplashScreenData(searchable: SavableSearchable?): SplashScreenData {
val context = LocalContext.current
val defaultBackgroundColor = MaterialTheme.colorScheme.background
val state = remember {
mutableStateOf(SplashScreenData(backgroundColor = defaultBackgroundColor))
mutableStateOf(SplashScreenData(backgroundColor = defaultBackgroundColor, iconSize = 288.dp))
}
LaunchedEffect(searchable) {
withContext(Dispatchers.IO) {
if (searchable is LauncherApp && isAtLeastApiLevel(31)) {
val activityInfo = searchable.launcherActivityInfo.activityInfo
if (searchable is LauncherApp) {
val activityInfo = if (isAtLeastApiLevel(31)) {
searchable.launcherActivityInfo.activityInfo
} else {
try {
context.packageManager.getActivityInfo(
searchable.launcherActivityInfo.componentName,
0
)
} catch (e: PackageManager.NameNotFoundException) {
null
}
} ?: return@withContext
val themeRes = activityInfo.themeResource
val ctx = context.createPackageContext(
searchable.`package`,
@ -101,28 +125,28 @@ fun rememberSplashScreenData(searchable: SavableSearchable?): SplashScreenData {
typedValue,
true
)
if (!typedValue.isColorType || typedValue.data == 0) {
if (!typedValue.isColor || typedValue.data == 0) {
theme.resolveAttribute(
android.R.attr.windowBackground,
typedValue,
true
)
}
if (!typedValue.isColorType || typedValue.data == 0) {
if (!typedValue.isColor || typedValue.data == 0) {
theme.resolveAttribute(
android.R.attr.colorBackground,
typedValue,
true
)
}
if (!typedValue.isColorType || typedValue.data == 0) {
if (!typedValue.isColor || typedValue.data == 0) {
theme.resolveAttribute(
android.R.attr.background,
typedValue,
true
)
}
val backgroundColor = typedValue.takeIf { it.isColorType && it.data != 0 }?.data
val backgroundColor = typedValue.takeIf { it.isColor && it.data != 0 }?.data
theme.resolveAttribute(
android.R.attr.windowSplashScreenAnimatedIcon,
@ -130,8 +154,12 @@ fun rememberSplashScreenData(searchable: SavableSearchable?): SplashScreenData {
true
)
val icon = if (typedValue.resourceId != 0) {
ContextCompat.getDrawable(ctx, typedValue.resourceId)
var icon = if (typedValue.resourceId != 0) {
try {
ContextCompat.getDrawable(ctx, typedValue.resourceId)
} catch (e: Resources.NotFoundException) {
null
}
} else {
null
}
@ -148,14 +176,39 @@ fun rememberSplashScreenData(searchable: SavableSearchable?): SplashScreenData {
null
}
theme.resolveAttribute(
android.R.attr.windowSplashScreenIconBackgroundColor,
typedValue,
true
)
var iconSize = 288.dp
var iconBackground = if (typedValue.isColor && typedValue.data != 0) {
iconSize = 240.dp
Color(typedValue.data)
} else {
null
}
if (icon == null) {
icon = activityInfo.loadIcon(context.packageManager)
iconSize = 160.dp
}
state.value = SplashScreenData(
backgroundColor = backgroundColor?.let { Color(it) } ?: defaultBackgroundColor,
icon = icon,
brandingIcon = brandingIcon
brandingIcon = brandingIcon,
iconBackground = iconBackground,
iconSize = iconSize,
)
}
}
}
return state.value
}
}
internal val TypedValue.isColor
get() = type in TypedValue.TYPE_FIRST_COLOR_INT..TypedValue.TYPE_LAST_COLOR_INT