自定义主题添加选择对比度的选项 #762

Merge pull request #762

* 手动选择对比度

* 样式优化&操作逻辑优化

* [优化] 优化代码,使用kolor自带的枚举值
This commit is contained in:
5151561
2026-03-25 01:35:14 +08:00
committed by GitHub
parent be63504a4d
commit 32806e2e26
11 changed files with 88 additions and 25 deletions
@@ -178,6 +178,7 @@ object PreferKey {
const val disableMangaScale = "disableMangaScale" const val disableMangaScale = "disableMangaScale"
const val firebaseEnable = "firebaseEnable" const val firebaseEnable = "firebaseEnable"
const val cPrimary = "colorPrimary" const val cPrimary = "colorPrimary"
const val customContrast = "customContrast"
const val cAccent = "colorAccent" const val cAccent = "colorAccent"
const val customMode = "customMode" const val customMode = "customMode"
const val paletteStyle = "paletteStyle" const val paletteStyle = "paletteStyle"
@@ -47,6 +47,10 @@ object ThemeConfig {
postEvent(EventBus.RECREATE, "") postEvent(EventBus.RECREATE, "")
} }
var customContrast by prefDelegate(PreferKey.customContrast, "Default") {
postEvent(EventBus.RECREATE, "")
}
var launcherIcon by prefDelegate(PreferKey.launcherIcon, "ic_launcher") var launcherIcon by prefDelegate(PreferKey.launcherIcon, "ic_launcher")
var showDiscovery by prefDelegate(PreferKey.showDiscovery, true) var showDiscovery by prefDelegate(PreferKey.showDiscovery, true)
@@ -68,4 +72,4 @@ object ThemeConfig {
fun hasImageBg(isDark: Boolean): Boolean = fun hasImageBg(isDark: Boolean): Boolean =
!(if (isDark) bgImageDark else bgImageLight).isNullOrBlank() !(if (isDark) bgImageDark else bgImageLight).isNullOrBlank()
} }
@@ -213,12 +213,12 @@ fun ThemeConfigScreen(
onClick = { showLauncherIconPicker = true } onClick = { showLauncherIconPicker = true }
) )
SwitchSettingItem( SwitchSettingItem(
title = "预见性返回手势", title = stringResource(R.string.predictive_back),
description = "启用系统预见性返回手势", description = stringResource(R.string.predictive_back_summary),
checked = ThemeConfig.isPredictiveBackEnabled, checked = ThemeConfig.isPredictiveBackEnabled,
onCheckedChange = { onCheckedChange = {
ThemeConfig.isPredictiveBackEnabled = it ThemeConfig.isPredictiveBackEnabled = it
context.toastOnUi("重启以应用") context.toastOnUi(R.string.restart_to_apply)
} }
) )
SliderSettingItem( SliderSettingItem(
@@ -239,14 +239,14 @@ fun ThemeConfigScreen(
} }
if (selectedTheme == "12") { if (selectedTheme == "12") {
SplicedColumnGroup(title = "自定义主题") { SplicedColumnGroup(title = stringResource(R.string.custom_theme)) {
ClickableSettingItem( ClickableSettingItem(
title = stringResource(R.string.seed_color), title = stringResource(R.string.seed_color),
option = if (primaryColorValue.intValue != 0) "#${ option = if (primaryColorValue.intValue != 0) "#${
Integer.toHexString( Integer.toHexString(
primaryColorValue.intValue primaryColorValue.intValue
).uppercase() ).uppercase()
}" else "点击选择", }" else stringResource(R.string.click_to_select),
onClick = { showColorPicker = true }, onClick = { showColorPicker = true },
trailingContent = { trailingContent = {
if (primaryColorValue.intValue != 0) { if (primaryColorValue.intValue != 0) {
@@ -271,6 +271,13 @@ fun ThemeConfigScreen(
entryValues = stringArrayResource(R.array.paletteStyle_value), entryValues = stringArrayResource(R.array.paletteStyle_value),
onValueChange = { ThemeConfig.paletteStyle = it } onValueChange = { ThemeConfig.paletteStyle = it }
) )
DropdownListSettingItem(
title = stringResource(R.string.preferred_contrast),
selectedValue = ThemeConfig.customContrast,
displayEntries = stringArrayResource(R.array.customContrast),
entryValues = stringArrayResource(R.array.customContrast_value),
onValueChange = { ThemeConfig.customContrast = it }
)
} }
} }
@@ -325,9 +332,9 @@ fun ThemeConfigScreen(
) )
} }
SplicedColumnGroup(title = "Compose 相关") { SplicedColumnGroup(title = stringResource(R.string.compose_related)) {
SwitchSettingItem( SwitchSettingItem(
title = "使用折叠应用栏", title = stringResource(R.string.use_flexible_top_bar),
checked = ThemeConfig.useFlexibleTopAppBar, checked = ThemeConfig.useFlexibleTopAppBar,
onCheckedChange = { ThemeConfig.useFlexibleTopAppBar = it } onCheckedChange = { ThemeConfig.useFlexibleTopAppBar = it }
) )
@@ -469,6 +476,7 @@ fun ThemeConfigScreen(
} }
) )
} }
} }
@OptIn(ExperimentalMaterial3ExpressiveApi::class) @OptIn(ExperimentalMaterial3ExpressiveApi::class)
@@ -1,30 +1,16 @@
package io.legado.app.ui.theme package io.legado.app.ui.theme
import android.app.UiModeManager
import android.content.Context
import android.os.Build
import androidx.compose.material3.ColorScheme import androidx.compose.material3.ColorScheme
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.core.content.getSystemService
import com.materialkolor.Contrast
import com.materialkolor.PaletteStyle import com.materialkolor.PaletteStyle
import com.materialkolor.dynamicColorScheme import com.materialkolor.dynamicColorScheme
class CustomColorScheme( class CustomColorScheme(
context: Context,
seed: Int, seed: Int,
style: PaletteStyle, style: PaletteStyle,
) : BaseColorScheme() { ) : BaseColorScheme() {
private val contrastLevel: Double = private val contrastLevel: Double = ThemeResolver.resolveContrastLevel()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
context.getSystemService<UiModeManager>()
?.contrast
?.toDouble()
?: Contrast.Default.value
} else {
Contrast.Default.value
}
override val lightScheme: ColorScheme = dynamicColorScheme( override val lightScheme: ColorScheme = dynamicColorScheme(
seedColor = Color(seed), seedColor = Color(seed),
@@ -65,7 +65,7 @@ object ThemeManager {
} }
AppThemeMode.CUSTOM -> { AppThemeMode.CUSTOM -> {
CustomColorScheme(context, context.primaryColor, style) CustomColorScheme(context.primaryColor, style)
.getColorScheme(darkTheme) .getColorScheme(darkTheme)
} }
@@ -1,6 +1,8 @@
package io.legado.app.ui.theme package io.legado.app.ui.theme
import com.materialkolor.Contrast
import com.materialkolor.PaletteStyle import com.materialkolor.PaletteStyle
import io.legado.app.ui.config.themeConfig.ThemeConfig
object ThemeResolver { object ThemeResolver {
@@ -37,4 +39,12 @@ object ThemeResolver {
} }
} }
fun resolveContrastLevel(): Double {
return try {
Contrast.valueOf(ThemeConfig.customContrast).value
} catch (e: Exception) {
Contrast.Default.value
}
}
} }
@@ -214,5 +214,11 @@
<item>仅封面</item> <item>仅封面</item>
</string-array> </string-array>
<string-array name="customContrast">
<item>默认</item>
<item>较强</item>
<item>最强</item>
</string-array>
<string name="all_version">所有版本</string> <string name="all_version">所有版本</string>
</resources> </resources>
+19 -1
View File
@@ -25,6 +25,24 @@
<string name="tip_cannot_jump_setting_page">无法跳转至设置界面</string> <string name="tip_cannot_jump_setting_page">无法跳转至设置界面</string>
<string name="manual_input">手动输入</string> <string name="manual_input">手动输入</string>
<string name="preferred_contrast">偏好对比度</string>
<string name="contrast_source_system_summary">来源:系统对比度</string>
<string name="contrast_source_manual_summary">来源:手动输入</string>
<string name="current_effective_contrast">当前生效值:%1$s</string>
<string name="system_contrast_value">系统对比度:%1$s</string>
<string name="system_contrast">系统对比度</string>
<string name="manual_contrast_value_label">手动值 [-1, 1]</string>
<string name="manual_contrast_invalid">请输入 -1 到 1 之间的有效数字</string>
<string name="predictive_back">预见性返回手势</string>
<string name="predictive_back_summary">启用系统预见性返回手势</string>
<string name="restart_to_apply">重启以应用</string>
<string name="custom_theme">自定义主题</string>
<string name="click_to_select">点击选择</string>
<string name="compose_related">Compose 相关</string>
<string name="use_flexible_top_bar">使用折叠应用栏</string>
<string name="slider">滑块</string>
<string name="input">输入</string>
<string name="manual_contrast_value_template">手动值:%1$s</string>
<string name="enter_directory_path">请输入目录路径</string> <string name="enter_directory_path">请输入目录路径</string>
<string name="invalid_directory">目录路径无效</string> <string name="invalid_directory">目录路径无效</string>
<string name="empty_directory_input">目录路径不能为空</string> <string name="empty_directory_input">目录路径不能为空</string>
@@ -1390,4 +1408,4 @@
<string name="enable_select_vibrator">选择文本时震动</string> <string name="enable_select_vibrator">选择文本时震动</string>
<string name="re_sync_webdav">重新同步远程书籍</string> <string name="re_sync_webdav">重新同步远程书籍</string>
<string name="underline_padding">离字间距</string> <string name="underline_padding">离字间距</string>
</resources> </resources>
+6
View File
@@ -131,4 +131,10 @@
<item>3</item> <item>3</item>
</string-array> </string-array>
<string-array name="customContrast_value">
<item>Default</item>
<item>Medium</item>
<item>High</item>
</string-array>
</resources> </resources>
+6
View File
@@ -299,5 +299,11 @@
<item>Unlabeled</item> <item>Unlabeled</item>
</string-array> </string-array>
<string-array name="customContrast">
<item>Default</item>
<item>High</item>
<item>Maximum</item>
</string-array>
<string name="all_version">所有版本</string> <string name="all_version">所有版本</string>
</resources> </resources>
+18
View File
@@ -26,6 +26,24 @@
<string name="tip_cannot_jump_setting_page">Cannot jump to Settings.</string> <string name="tip_cannot_jump_setting_page">Cannot jump to Settings.</string>
<string name="manual_input">Manual Input</string> <string name="manual_input">Manual Input</string>
<string name="preferred_contrast">Preferred contrast</string>
<string name="contrast_source_system_summary">Source: System contrast</string>
<string name="contrast_source_manual_summary">Source: Manual input</string>
<string name="current_effective_contrast">Current effective value: %1$s</string>
<string name="system_contrast_value">System contrast: %1$s</string>
<string name="system_contrast">System contrast</string>
<string name="manual_contrast_value_label">Manual value [-1, 1]</string>
<string name="manual_contrast_invalid">Enter a valid number between -1 and 1</string>
<string name="predictive_back">Predictive Back Gestures</string>
<string name="predictive_back_summary">Enable system predictive back gestures</string>
<string name="restart_to_apply">Restart to apply</string>
<string name="custom_theme">Custom Theme</string>
<string name="click_to_select">Click to select</string>
<string name="compose_related">Compose Related</string>
<string name="use_flexible_top_bar">Use flexible top app bar</string>
<string name="slider">Slider</string>
<string name="input">Input</string>
<string name="manual_contrast_value_template">Manual value: %1$s</string>
<string name="enter_directory_path">Enter directory path</string> <string name="enter_directory_path">Enter directory path</string>
<string name="invalid_directory">Invalid directory path</string> <string name="invalid_directory">Invalid directory path</string>
<string name="empty_directory_input">Directory path cannot be empty</string> <string name="empty_directory_input">Directory path cannot be empty</string>