[优化] 为Compose界面实现了View系统的主题系统
This commit is contained in:
@@ -19,6 +19,8 @@ import io.legado.app.constant.Theme
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.help.config.ThemeConfig
|
||||
import io.legado.app.lib.theme.primaryColor
|
||||
import io.legado.app.ui.theme.AppTheme
|
||||
import io.legado.app.ui.theme.ThemeState
|
||||
import io.legado.app.utils.disableAutoFill
|
||||
import io.legado.app.utils.fullScreen
|
||||
import io.legado.app.utils.getPrefString
|
||||
@@ -39,7 +41,6 @@ abstract class BaseComposeActivity(
|
||||
protected abstract fun Content()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
initTheme()
|
||||
window.decorView.disableAutoFill()
|
||||
AppContextWrapper.applyLocaleAndFont(this)
|
||||
|
||||
@@ -49,7 +50,7 @@ abstract class BaseComposeActivity(
|
||||
// Compose 入口
|
||||
setContent {
|
||||
AppTheme {
|
||||
Surface(color = MaterialTheme.colorScheme.background) {
|
||||
Surface() {
|
||||
Content()
|
||||
}
|
||||
}
|
||||
@@ -84,64 +85,9 @@ abstract class BaseComposeActivity(
|
||||
|
||||
open fun observeLiveBus() {
|
||||
observeEvent<String>(EventBus.RECREATE) {
|
||||
ThemeState.updateThemeMode()
|
||||
recreate()
|
||||
}
|
||||
}
|
||||
|
||||
open fun initTheme() {
|
||||
when (getPrefString("app_theme", "0")) {
|
||||
"0" -> {
|
||||
DynamicColors.applyToActivitiesIfAvailable(application)
|
||||
}
|
||||
"1" -> setTheme(R.style.Theme_Base_GR)
|
||||
"2" -> setTheme(R.style.Theme_Base_Lemon)
|
||||
"3" -> setTheme(R.style.Theme_Base_WH)
|
||||
"4" -> setTheme(R.style.Theme_Base_Elink)
|
||||
"5" -> setTheme(R.style.Theme_Base_Sora)
|
||||
"6" -> setTheme(R.style.Theme_Base_August)
|
||||
"7" -> setTheme(R.style.Theme_Base_Carlotta)
|
||||
"8" -> setTheme(R.style.Theme_Base_Koharu)
|
||||
"9" -> setTheme(R.style.Theme_Base_Yuuka)
|
||||
"10" -> setTheme(R.style.Theme_Base_Phoebe)
|
||||
"11" -> setTheme(R.style.Theme_Base_Mujika)
|
||||
"12" -> {
|
||||
if (AppConfig.customMode == "accent")
|
||||
setTheme(R.style.ThemeOverlay_WhiteBackground)
|
||||
|
||||
val colorImagePath = getPrefString(PreferKey.colorImage)
|
||||
if (!colorImagePath.isNullOrBlank()) {
|
||||
val file = File(colorImagePath)
|
||||
if (file.exists()) {
|
||||
val bitmap = BitmapFactory.decodeFile(file.absolutePath)
|
||||
if (bitmap != null) {
|
||||
val colorAccuracy = true
|
||||
val targetWidth = if (colorAccuracy) (bitmap.width / 4).coerceAtMost(256) else 16
|
||||
val targetHeight = if (colorAccuracy) (bitmap.height / 4).coerceAtMost(256) else 16
|
||||
val scaledBitmap = bitmap.scale(targetWidth, targetHeight, false)
|
||||
|
||||
val options = DynamicColorsOptions.Builder()
|
||||
.setContentBasedSource(scaledBitmap)
|
||||
.build()
|
||||
|
||||
DynamicColors.applyToActivitiesIfAvailable(application, options)
|
||||
bitmap.recycle()
|
||||
}
|
||||
}
|
||||
}else{
|
||||
DynamicColors.applyToActivitiesIfAvailable(
|
||||
application,
|
||||
DynamicColorsOptions.Builder()
|
||||
.setContentBasedSource(application.primaryColor)
|
||||
.build()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
"13" -> setTheme(R.style.AppTheme_Transparent)
|
||||
}
|
||||
|
||||
if (AppConfig.pureBlack)
|
||||
setTheme(R.style.ThemeOverlay_PureBlack)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package io.legado.app.base
|
||||
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun AppTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
dynamicColor: Boolean = true,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val motionScheme = MotionScheme.expressive()
|
||||
val colorScheme = when {
|
||||
dynamicColor && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S ->
|
||||
if (darkTheme) dynamicDarkColorScheme(context)
|
||||
else dynamicLightColorScheme(context)
|
||||
|
||||
darkTheme -> darkColorScheme()
|
||||
else -> lightColorScheme()
|
||||
}
|
||||
|
||||
MaterialExpressiveTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = AppTypography,
|
||||
motionScheme = motionScheme,
|
||||
shapes = AppShapes,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
// Material3 Typography
|
||||
val AppTypography = Typography()
|
||||
|
||||
// Material3 Shapes
|
||||
val AppShapes = Shapes()
|
||||
@@ -12,6 +12,7 @@ import io.legado.app.ui.book.bookmark.AllBookmarkViewModel
|
||||
import io.legado.app.ui.book.explore.ExploreShowViewModel
|
||||
import io.legado.app.ui.book.readRecord.ReadRecordViewModel
|
||||
import io.legado.app.ui.book.searchContent.SearchContentViewModel
|
||||
import io.legado.app.ui.main.my.MyViewModel
|
||||
import io.legado.app.ui.replace.ReplaceRuleViewModel
|
||||
import io.legado.app.ui.replace.edit.ReplaceEditViewModel
|
||||
import org.koin.android.ext.koin.androidApplication
|
||||
@@ -49,4 +50,6 @@ val appModule = module {
|
||||
single { SearchContentRepository() }
|
||||
single { BookRepository() }
|
||||
viewModel { SearchContentViewModel(get(), get()) }
|
||||
|
||||
viewModel { MyViewModel(get()) }
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
val isCronet = appCtx.getPrefBoolean(PreferKey.cronet)
|
||||
var useAntiAlias = appCtx.getPrefBoolean(PreferKey.antiAlias)
|
||||
var userAgent: String = getPrefUserAgent()
|
||||
|
||||
var isEInkMode = appCtx.getPrefString("app_theme", "0") == "4"
|
||||
var isTransparent = appCtx.getPrefString("app_theme", "0") == "13"
|
||||
var customMode = appCtx.getPrefString(PreferKey.customMode)
|
||||
@@ -51,6 +52,7 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
var mangaClickActionBR = appCtx.getPrefInt(PreferKey.mangaClickActionBR, 1)
|
||||
|
||||
var themeMode = appCtx.getPrefString(PreferKey.themeMode, "0")
|
||||
var AppTheme = appCtx.getPrefString(PreferKey.appTheme, "0")
|
||||
var useDefaultCover = appCtx.getPrefBoolean(PreferKey.useDefaultCover, false)
|
||||
var optimizeRender = CanvasRecorderFactory.isSupport
|
||||
&& appCtx.getPrefBoolean(PreferKey.optimizeRender, false)
|
||||
@@ -59,6 +61,10 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||
when (key) {
|
||||
|
||||
PreferKey.appTheme -> {
|
||||
AppTheme = appCtx.getPrefString(PreferKey.appTheme, "0")
|
||||
}
|
||||
|
||||
PreferKey.themeMode -> {
|
||||
themeMode = appCtx.getPrefString(PreferKey.themeMode, "0")
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.legado.app.base.AppTheme
|
||||
import io.legado.app.ui.theme.AppTheme
|
||||
import io.legado.app.base.BaseComposeActivity
|
||||
import io.legado.app.ui.book.changecover.ChangeCoverDialog
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package io.legado.app.ui.book.readRecord
|
||||
import android.os.Bundle
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import io.legado.app.base.AppTheme
|
||||
import io.legado.app.ui.theme.AppTheme
|
||||
import io.legado.app.data.appDb
|
||||
import io.legado.app.utils.startActivityForBook
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
||||
@@ -2,7 +2,7 @@ package io.legado.app.ui.book.searchContent
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.legado.app.base.AppTheme
|
||||
import io.legado.app.ui.theme.AppTheme
|
||||
import io.legado.app.base.BaseComposeActivity
|
||||
|
||||
class SearchContentActivity : BaseComposeActivity() {
|
||||
|
||||
@@ -4,7 +4,7 @@ import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.legado.app.base.AppTheme
|
||||
import io.legado.app.ui.theme.AppTheme
|
||||
import io.legado.app.base.BaseComposeActivity
|
||||
|
||||
class ReplaceRuleActivity : BaseComposeActivity() {
|
||||
|
||||
@@ -4,7 +4,7 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.runtime.Composable
|
||||
import io.legado.app.base.AppTheme
|
||||
import io.legado.app.ui.theme.AppTheme
|
||||
import io.legado.app.base.BaseComposeActivity
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
package io.legado.app.ui.theme
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.MaterialExpressiveTheme
|
||||
import androidx.compose.material3.MotionScheme
|
||||
import androidx.compose.material3.Shapes
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import io.legado.app.ui.theme.AppColorSchemes.AugustDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.AugustLightColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.CarlottaDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.CarlottaLightColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.ElinkDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.ElinkLightColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.GRDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.GRLightColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.KoharuDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.KoharuLightColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.LemonDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.LemonLightColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.MujikaDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.MujikaLightColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.PhoebeDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.PhoebeLightColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.SoraDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.SoraLightColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.TransparentDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.TransparentLightColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.WHDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.WHLightColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.YuukaDarkColorScheme
|
||||
import io.legado.app.ui.theme.AppColorSchemes.YuukaLightColorScheme
|
||||
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun AppTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val motionScheme = MotionScheme.expressive()
|
||||
val appThemeMode by ThemeState.themeMode.collectAsState()
|
||||
|
||||
var colorScheme = when (appThemeMode) {
|
||||
AppThemeMode.Dynamic, AppThemeMode.ContentBased -> {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
||||
} else {
|
||||
if (darkTheme) darkColorScheme() else lightColorScheme()
|
||||
}
|
||||
}
|
||||
AppThemeMode.GR -> if (darkTheme) GRDarkColorScheme else GRLightColorScheme
|
||||
AppThemeMode.Lemon -> if (darkTheme) LemonDarkColorScheme else LemonLightColorScheme
|
||||
AppThemeMode.WH -> if (darkTheme) WHDarkColorScheme else WHLightColorScheme
|
||||
AppThemeMode.Elink -> if (darkTheme) ElinkDarkColorScheme else ElinkLightColorScheme
|
||||
AppThemeMode.Sora -> if (darkTheme) SoraDarkColorScheme else SoraLightColorScheme
|
||||
AppThemeMode.August -> if (darkTheme) AugustDarkColorScheme else AugustLightColorScheme
|
||||
AppThemeMode.Carlotta -> if (darkTheme) CarlottaDarkColorScheme else CarlottaLightColorScheme
|
||||
AppThemeMode.Koharu -> if (darkTheme) KoharuDarkColorScheme else KoharuLightColorScheme
|
||||
AppThemeMode.Yuuka -> if (darkTheme) YuukaDarkColorScheme else YuukaLightColorScheme
|
||||
AppThemeMode.Phoebe -> if (darkTheme) PhoebeDarkColorScheme else PhoebeLightColorScheme
|
||||
AppThemeMode.Mujika -> if (darkTheme) MujikaDarkColorScheme else MujikaLightColorScheme
|
||||
AppThemeMode.Transparent -> if (darkTheme) TransparentDarkColorScheme else TransparentLightColorScheme
|
||||
}
|
||||
|
||||
if (darkTheme && AppConfig.pureBlack) {
|
||||
colorScheme = colorScheme.copy(
|
||||
background = Color.Black,
|
||||
surface = Color.Black
|
||||
)
|
||||
}
|
||||
|
||||
MaterialExpressiveTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = AppTypography,
|
||||
motionScheme = motionScheme,
|
||||
shapes = AppShapes,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
// Material3 Typography
|
||||
val AppTypography = Typography()
|
||||
|
||||
// Material3 Shapes
|
||||
val AppShapes = Shapes()
|
||||
@@ -0,0 +1,36 @@
|
||||
package io.legado.app.ui.theme
|
||||
|
||||
enum class AppThemeMode {
|
||||
Dynamic,
|
||||
GR,
|
||||
Lemon,
|
||||
WH,
|
||||
Elink,
|
||||
Sora,
|
||||
August,
|
||||
Carlotta,
|
||||
Koharu,
|
||||
Yuuka,
|
||||
Phoebe,
|
||||
Mujika,
|
||||
ContentBased,
|
||||
Transparent
|
||||
}
|
||||
|
||||
fun resolveThemeMode(value: String): AppThemeMode = when (value) {
|
||||
"0" -> AppThemeMode.Dynamic
|
||||
"1" -> AppThemeMode.GR
|
||||
"2" -> AppThemeMode.Lemon
|
||||
"3" -> AppThemeMode.WH
|
||||
"4" -> AppThemeMode.Elink
|
||||
"5" -> AppThemeMode.Sora
|
||||
"6" -> AppThemeMode.August
|
||||
"7" -> AppThemeMode.Carlotta
|
||||
"8" -> AppThemeMode.Koharu
|
||||
"9" -> AppThemeMode.Yuuka
|
||||
"10" -> AppThemeMode.Phoebe
|
||||
"11" -> AppThemeMode.Mujika
|
||||
"12" -> AppThemeMode.ContentBased
|
||||
"13" -> AppThemeMode.Transparent
|
||||
else -> AppThemeMode.Dynamic
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,16 @@
|
||||
package io.legado.app.ui.theme
|
||||
|
||||
import io.legado.app.help.config.AppConfig
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
object ThemeState {
|
||||
private val _themeMode =
|
||||
MutableStateFlow(resolveThemeMode(AppConfig.AppTheme.toString()))
|
||||
|
||||
val themeMode: StateFlow<AppThemeMode> = _themeMode
|
||||
|
||||
fun updateThemeMode() {
|
||||
_themeMode.value = resolveThemeMode(AppConfig.AppTheme.toString())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user