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