feat: 应用图标动态取色

This commit is contained in:
HuanCheng65 2023-09-29 22:30:44 +08:00
parent e4c61fb00d
commit eecc703c7f
No known key found for this signature in database
GPG Key ID: 5EC9DD60A32C7360
23 changed files with 160 additions and 21 deletions

View File

@ -166,8 +166,7 @@
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:scheme="tblite" />
<data android:scheme="tblite" />
</intent-filter>
<meta-data
@ -175,6 +174,24 @@
android:resource="@xml/shortcut_new" />
</activity>
<activity-alias
android:name=".MainActivityIconThemed"
android:enabled="false"
android:exported="true"
android:icon="@mipmap/ic_launcher_new_themed"
android:roundIcon="@mipmap/ic_launcher_new_themed_round"
android:targetActivity=".MainActivityV2">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcut_new" />
</activity-alias>
<activity-alias
android:name=".MainActivityIconInvert"
android:enabled="false"

View File

@ -43,7 +43,7 @@ import com.huanchengfly.tieba.post.utils.AppIconUtil.enableComponent
import com.huanchengfly.tieba.post.utils.BlockManager
import com.huanchengfly.tieba.post.utils.ClientUtils
import com.huanchengfly.tieba.post.utils.EmoticonManager
import com.huanchengfly.tieba.post.utils.Icons
import com.huanchengfly.tieba.post.utils.LauncherIcons
import com.huanchengfly.tieba.post.utils.SharedPreferencesUtil
import com.huanchengfly.tieba.post.utils.ThemeUtil
import com.huanchengfly.tieba.post.utils.TiebaUtil
@ -113,7 +113,7 @@ class App : Application(), IApp, SketchFactory {
) {
setOldMainActivityEnabled(!enableNewUi || keepOld)
if (enableNewUi) AppIconUtil.setIcon()
else AppIconUtil.setIcon(Icons.DISABLE)
else AppIconUtil.setIcon(LauncherIcons.DISABLE)
}
override fun onCreate() {

View File

@ -1,5 +1,6 @@
package com.huanchengfly.tieba.post.ui.page.settings.custom
import android.os.Build
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
@ -11,11 +12,15 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Apps
import androidx.compose.material.icons.outlined.Brightness2
import androidx.compose.material.icons.outlined.BrightnessAuto
import androidx.compose.material.icons.outlined.ColorLens
import androidx.compose.material.icons.outlined.Explore
import androidx.compose.material.icons.outlined.FontDownload
import androidx.compose.material.icons.outlined.FormatColorFill
import androidx.compose.material.icons.outlined.ViewAgenda
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@ -24,11 +29,13 @@ import androidx.compose.ui.res.stringArrayResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.datastore.preferences.core.stringPreferencesKey
import com.google.accompanist.drawablepainter.rememberDrawablePainter
import com.huanchengfly.tieba.post.R
import com.huanchengfly.tieba.post.activities.AppFontSizeActivity
import com.huanchengfly.tieba.post.dataStore
import com.huanchengfly.tieba.post.goToActivity
import com.huanchengfly.tieba.post.rememberPreferenceAsState
import com.huanchengfly.tieba.post.ui.common.prefs.PrefsScreen
import com.huanchengfly.tieba.post.ui.common.prefs.widgets.ListPref
import com.huanchengfly.tieba.post.ui.common.prefs.widgets.SwitchPref
@ -40,9 +47,11 @@ import com.huanchengfly.tieba.post.ui.widgets.compose.MyScaffold
import com.huanchengfly.tieba.post.ui.widgets.compose.Sizes
import com.huanchengfly.tieba.post.ui.widgets.compose.TitleCentredToolbar
import com.huanchengfly.tieba.post.utils.AppIconUtil
import com.huanchengfly.tieba.post.utils.LauncherIcons
import com.huanchengfly.tieba.post.utils.ThemeUtil
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.collections.immutable.persistentListOf
@OptIn(ExperimentalMaterialApi::class, ExperimentalComposeUiApi::class)
@Destination
@ -119,7 +128,7 @@ fun CustomSettingsPage(
ListPref(
key = "app_icon",
title = stringResource(id = R.string.settings_app_icon),
defaultValue = com.huanchengfly.tieba.post.utils.Icons.DEFAULT_ICON,
defaultValue = LauncherIcons.DEFAULT_ICON,
leadingIcon = {
LeadingIcon {
AvatarIcon(
@ -130,12 +139,12 @@ fun CustomSettingsPage(
}
},
entries = mapOf(
com.huanchengfly.tieba.post.utils.Icons.NEW_ICON to "新图标",
com.huanchengfly.tieba.post.utils.Icons.NEW_ICON_INVERT to "新图标(反色)",
com.huanchengfly.tieba.post.utils.Icons.OLD_ICON to "旧图标",
LauncherIcons.NEW_ICON to "新图标",
LauncherIcons.NEW_ICON_INVERT to "新图标(反色)",
LauncherIcons.OLD_ICON to "旧图标",
),
icons = mapOf(
com.huanchengfly.tieba.post.utils.Icons.NEW_ICON to {
LauncherIcons.NEW_ICON to {
Image(
painter = rememberDrawablePainter(
drawable = LocalContext.current.getDrawable(
@ -146,7 +155,7 @@ fun CustomSettingsPage(
modifier = Modifier.size(Sizes.Medium)
)
},
com.huanchengfly.tieba.post.utils.Icons.NEW_ICON_INVERT to {
LauncherIcons.NEW_ICON_INVERT to {
Image(
painter = rememberDrawablePainter(
drawable = LocalContext.current.getDrawable(
@ -157,7 +166,7 @@ fun CustomSettingsPage(
modifier = Modifier.size(Sizes.Medium)
)
},
com.huanchengfly.tieba.post.utils.Icons.OLD_ICON to {
LauncherIcons.OLD_ICON to {
Image(
painter = rememberDrawablePainter(
drawable = LocalContext.current.getDrawable(
@ -169,10 +178,48 @@ fun CustomSettingsPage(
)
},
),
onValueChange = { AppIconUtil.setIcon(it) },
onValueChange = { AppIconUtil.setIcon(icon = it) },
useSelectedAsSummary = true,
)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
prefsItem {
val supportThemedIcons = remember {
persistentListOf(
LauncherIcons.NEW_ICON,
// LauncherIcons.NEW_ICON_INVERT,
)
}
val currentLauncherIcon by rememberPreferenceAsState(
key = stringPreferencesKey("app_icon"),
defaultValue = LauncherIcons.NEW_ICON
)
val isCurrentSupportThemedIcon by remember {
derivedStateOf {
supportThemedIcons.contains(currentLauncherIcon)
}
}
SwitchPref(
key = "useThemedIcon",
title = stringResource(id = R.string.title_settings_use_themed_icon),
defaultChecked = false,
enabled = isCurrentSupportThemedIcon,
leadingIcon = {
LeadingIcon {
AvatarIcon(
icon = Icons.Outlined.ColorLens,
size = Sizes.Small,
contentDescription = null,
)
}
},
onCheckedChange = {
AppIconUtil.setIcon(isThemed = it)
},
summary = stringResource(id = R.string.tip_settings_use_themed_icon_summary_not_supported).takeUnless { isCurrentSupportThemedIcon },
)
}
}
prefsItem {
SwitchPref(
key = "follow_system_night",

View File

@ -4,17 +4,24 @@ import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager
import com.huanchengfly.tieba.post.App
import kotlinx.collections.immutable.persistentListOf
object Icons {
object LauncherIcons {
const val NEW_ICON = "com.huanchengfly.tieba.post.MainActivityV2"
const val NEW_ICON_THEMED = "com.huanchengfly.tieba.post.MainActivityIconThemed"
const val NEW_ICON_INVERT = "com.huanchengfly.tieba.post.MainActivityIconInvert"
const val OLD_ICON = "com.huanchengfly.tieba.post.MainActivityIconOld"
const val DISABLE = "com.huanchengfly.tieba.post.MainActivityV2Disabled"
const val DEFAULT_ICON = NEW_ICON
val ICONS = listOf(NEW_ICON, NEW_ICON_INVERT, OLD_ICON)
val ICONS = persistentListOf(NEW_ICON, NEW_ICON_THEMED, NEW_ICON_INVERT, OLD_ICON)
val SUPPORT_THEMED_ICON = persistentListOf(NEW_ICON)
val THEMED_ICON_MAPPING = mapOf(
NEW_ICON to NEW_ICON_THEMED,
)
}
object AppIconUtil {
@ -26,11 +33,18 @@ object AppIconUtil {
private val appPreferences: AppPreferencesUtils
get() = context.appPreferences
fun setIcon(icon: String = appPreferences.appIcon ?: Icons.NEW_ICON) {
val newIcon = if (Icons.ICONS.contains(icon) || icon == Icons.DISABLE) {
fun setIcon(
icon: String = appPreferences.appIcon ?: LauncherIcons.NEW_ICON,
isThemed: Boolean = appPreferences.useThemedIcon,
) {
val useThemedIcon = isThemed && LauncherIcons.SUPPORT_THEMED_ICON.contains(icon)
var newIcon = if (LauncherIcons.ICONS.contains(icon) || icon == LauncherIcons.DISABLE) {
icon
} else Icons.DEFAULT_ICON
Icons.ICONS.forEach {
} else LauncherIcons.DEFAULT_ICON
if (useThemedIcon) {
newIcon = LauncherIcons.THEMED_ICON_MAPPING[newIcon] ?: newIcon
}
LauncherIcons.ICONS.forEach {
if (it == newIcon) {
context.packageManager.enableComponent(ComponentName(context, it))
} else {

View File

@ -53,10 +53,12 @@ open class AppPreferencesUtils private constructor(ctx: Context) {
var ignoreBatteryOptimizationsDialog by DataStoreDelegates.boolean(defaultValue = false)
var appIcon by DataStoreDelegates.string(
defaultValue = Icons.DEFAULT_ICON,
defaultValue = LauncherIcons.DEFAULT_ICON,
key = AppIconUtil.PREF_KEY_APP_ICON
)
var useThemedIcon by DataStoreDelegates.boolean(defaultValue = false)
var autoSign by DataStoreDelegates.boolean(defaultValue = false, key = "auto_sign")
var autoSignTime by DataStoreDelegates.string(

View File

@ -0,0 +1,27 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="100"
android:viewportHeight="100">
<group
android:scaleX="0.67"
android:scaleY="0.67"
android:translateX="16.5"
android:translateY="16.5">
<group>
<clip-path android:pathData="M0,-0h100v100h-100z" />
<path
android:fillColor="@color/ic_launcher_new_themed_foreground_1"
android:pathData="M29.69,38.34L71.31,38.34A7,7 0,0 1,78.31 45.34L78.31,93A7,7 0,0 1,71.31 100L29.69,100A7,7 0,0 1,22.69 93L22.69,45.34A7,7 0,0 1,29.69 38.34z" />
<path
android:fillColor="#fff"
android:pathData="M23.94,48.31L76.06,48.31c4.56,0 8.25,4.4 8.25,9.83L84.31,100L15.69,100L15.69,58.14C15.69,52.71 19.39,48.31 23.94,48.31Z" />
<path
android:fillColor="@color/ic_launcher_new_themed_foreground_2"
android:pathData="M28.8,64.71L71.2,64.71A3.31,3.31 0,0 1,74.51 68.02L74.51,68.02A3.31,3.31 0,0 1,71.2 71.33L28.8,71.33A3.31,3.31 0,0 1,25.49 68.02L25.49,68.02A3.31,3.31 0,0 1,28.8 64.71z" />
<path
android:fillColor="@color/ic_launcher_new_themed_foreground_2"
android:pathData="M28.8,76.98L54.53,76.98A3.31,3.31 0,0 1,57.84 80.29L57.84,80.29A3.31,3.31 0,0 1,54.53 83.61L28.8,83.61A3.31,3.31 0,0 1,25.49 80.29L25.49,80.29A3.31,3.31 0,0 1,28.8 76.98z" />
</group>
</group>
</vector>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_new_background" />
<foreground android:drawable="@drawable/ic_launcher_new_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_new_monochrome" />
</adaptive-icon>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_new_background" />
<foreground android:drawable="@drawable/ic_launcher_new_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_new_monochrome" />
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_new_themed_background" />
<foreground android:drawable="@drawable/ic_launcher_new_themed_foreground" />
</adaptive-icon>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_new_themed_background" />
<foreground android:drawable="@drawable/ic_launcher_new_themed_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_new_themed_background">@android:color/system_accent1_600</color>
<color name="ic_launcher_new_themed_foreground_1">@android:color/system_accent1_300</color>
<color name="ic_launcher_new_themed_foreground_2">@android:color/system_accent1_600</color>
</resources>

View File

@ -4,6 +4,10 @@
<color name="ic_launcher_new_invert_background">#FFFFFFFF</color>
<color name="ic_launcher_background">#FF2E60B0</color>
<color name="ic_launcher_new_themed_background">#FF5588D7</color>
<color name="ic_launcher_new_themed_foreground_1">#FFA7C5F0</color>
<color name="ic_launcher_new_themed_foreground_2">#FF538ACE</color>
<color name="colorPrimary">#FFFFFFFF</color>
<color name="colorAccent">#FF4477E0</color>
<color name="colorUnselected">#FFCCCCCC</color>
@ -13,8 +17,6 @@
<color name="color_place_holder_night">#99000000</color>
<color name="color_shadow">#FEE9E9E9</color>
<color name="t">#00BFA5</color>
<color name="color_switch_track_bg">#C4C4C4</color>
<color name="color_swipe_refresh_bg">#FFF</color>

View File

@ -727,4 +727,6 @@
<string name="settings_image_darken_when_night_mode">夜间模式压暗缩略图</string>
<string name="tip_toolbar_primary_color_summary">修改重启后生效</string>
<string name="title_hide_reply">隐藏回贴入口</string>
<string name="title_settings_use_themed_icon">应用图标使用动态取色</string>
<string name="tip_settings_use_themed_icon_summary_not_supported">当前正在使用的应用图标暂不支持动态取色</string>
</resources>