新增选择图片创建主题颜色功能

This commit is contained in:
HapeLee
2025-10-19 00:40:46 +08:00
parent 0d671df389
commit 45c953024f
9 changed files with 218 additions and 43 deletions
+31 -3
View File
@@ -7,7 +7,9 @@ import android.app.NotificationManager
import android.content.Context
import android.content.pm.ApplicationInfo
import android.content.res.Configuration
import android.graphics.BitmapFactory
import android.os.Build
import androidx.core.graphics.scale
import com.github.liuyueyi.quick.transfer.constants.TransType
import com.google.android.material.color.DynamicColors
import com.google.android.material.color.DynamicColorsOptions
@@ -59,6 +61,7 @@ import kotlinx.coroutines.launch
import org.chromium.base.ThreadUtils
import splitties.init.appCtx
import splitties.systemservices.notificationManager
import java.io.File
import java.net.URL
import java.util.concurrent.TimeUnit
import java.util.logging.Level
@@ -72,9 +75,34 @@ class App : Application() {
if (getPrefString("app_theme", "0") == "11") {
if (AppConfig.customMode == "accent")
setTheme(R.style.ThemeOverlay_WhiteBackground)
DynamicColors.applyToActivitiesIfAvailable(this, DynamicColorsOptions.Builder()
.setContentBasedSource(this.primaryColor)
.build())
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(this, options)
bitmap.recycle()
}
}
}else{
DynamicColors.applyToActivitiesIfAvailable(
this,
DynamicColorsOptions.Builder()
.setContentBasedSource(this.primaryColor)
.build()
)
}
}
super.onCreate()
@@ -3,6 +3,7 @@ package io.legato.kazusa.base
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.Configuration
import android.graphics.BitmapFactory
import android.graphics.Color
import android.os.Build
import android.os.Bundle
@@ -14,6 +15,7 @@ import android.view.View
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.graphics.drawable.toDrawable
import androidx.core.graphics.scale
import androidx.core.view.WindowCompat
import androidx.viewbinding.ViewBinding
import com.google.android.material.appbar.AppBarLayout
@@ -22,6 +24,7 @@ import com.google.android.material.color.DynamicColorsOptions
import io.legato.kazusa.R
import io.legato.kazusa.constant.AppLog
import io.legato.kazusa.constant.EventBus
import io.legato.kazusa.constant.PreferKey
import io.legato.kazusa.constant.Theme
import io.legato.kazusa.help.config.AppConfig
import io.legato.kazusa.help.config.ThemeConfig
@@ -38,6 +41,7 @@ import io.legato.kazusa.utils.fullScreen
import io.legato.kazusa.utils.setNavigationBarColorAuto
import io.legato.kazusa.utils.setStatusBarColorAuto
import io.legato.kazusa.utils.themeColor
import java.io.File
abstract class BaseActivity<VB : ViewBinding>(
@@ -169,11 +173,36 @@ abstract class BaseActivity<VB : ViewBinding>(
"11" -> {
if (AppConfig.customMode == "accent")
setTheme(R.style.ThemeOverlay_WhiteBackground)
DynamicColors.applyToActivitiesIfAvailable(application, DynamicColorsOptions.Builder()
.setContentBasedSource(application.primaryColor)
.build())
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()
)
}
}
"12" -> setTheme(R.style.AppTheme_Transparent)
}
@@ -205,4 +205,6 @@ object PreferKey {
const val pureBlack = "pure_black"
const val labelVisibilityMode = "labelVisibilityMode"
const val menuAlpha = "menuAlpha"
const val colorImage = "colorImage"
}
@@ -0,0 +1,53 @@
package io.legato.kazusa.lib.prefs
import android.content.Context
import android.graphics.BitmapFactory
import android.net.Uri
import android.util.AttributeSet
import android.view.View
import android.widget.ImageView
import androidx.preference.PreferenceViewHolder
import io.legato.kazusa.R
import java.io.File
class ImagePreviewPreference(context: Context, attrs: AttributeSet) : Preference(context, attrs) {
private var preview: ImageView? = null
init {
layoutResource = R.layout.view_preference
widgetLayoutResource = R.layout.view_icon
}
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
val v = Preference.bindView<ImageView>(
context, holder, icon, title, summary,
widgetLayoutResource,
R.id.preview,
50,
50
)
preview = v
updatePreview()
}
fun updatePreview() {
val path = sharedPreferences?.getString(key, null)
val view = preview ?: return
if (!path.isNullOrBlank()) {
val file = File(path)
if (file.exists()) {
val bitmap = BitmapFactory.decodeFile(path)
view.setImageBitmap(bitmap)
view.visibility = View.VISIBLE
return
}
}
view.setImageDrawable(null)
view.visibility = View.GONE
}
}
@@ -58,10 +58,12 @@ class ThemeConfigFragment : PreferenceFragmentCompat(),
SharedPreferences.OnSharedPreferenceChangeListener
//MenuProvider
{
private val requestCodeBgLight = 121
private val requestCodeBgDark = 122
private val requestCodeBgLight = 121
private val requestCodeBgDark = 122
private val selectImage = registerForActivityResult(SelectImageContract()) {
private val requestCodeColorImage = 123
private val selectImage = registerForActivityResult(SelectImageContract()) {
it.uri?.let { uri ->
when (it.requestCode) {
requestCodeBgLight -> setBgFromUri(uri, PreferKey.bgImage) {
@@ -71,6 +73,10 @@ class ThemeConfigFragment : PreferenceFragmentCompat(),
requestCodeBgDark -> setBgFromUri(uri, PreferKey.bgImageN) {
upTheme(true)
}
requestCodeColorImage -> setBgFromUri(uri, PreferKey.colorImage) {
upPreferenceSummary(PreferKey.colorImage, getPrefString(PreferKey.colorImage))
}
}
}
}
@@ -78,8 +84,6 @@ class ThemeConfigFragment : PreferenceFragmentCompat(),
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.pref_config_theme)
upPreferenceSummary(PreferKey.bgImage, getPrefString(PreferKey.bgImage))
upPreferenceSummary(PreferKey.bgImageN, getPrefString(PreferKey.bgImageN))
upPreferenceSummary(PreferKey.fontScale)
findPreference<ColorPreference>(PreferKey.cBackground)?.let {
@@ -129,6 +133,18 @@ class ThemeConfigFragment : PreferenceFragmentCompat(),
customMode?.isVisible = newValue == "11"
true
}
val hasColorImage = !getPrefString(PreferKey.colorImage).isNullOrBlank()
colorPrimary?.isEnabled = !hasColorImage
if (hasColorImage)
{
upPreferenceSummary("colorPrimary", getString(R.string.seed_photo_alart))
upPreferenceSummary(PreferKey.colorImage, getString(R.string.click_to_delete))
}
if (!getPrefString(PreferKey.bgImage).isNullOrBlank())
upPreferenceSummary(PreferKey.bgImage, getString(R.string.click_to_delete))
if (!getPrefString(PreferKey.bgImageN).isNullOrBlank())
upPreferenceSummary(PreferKey.bgImageN, getString(R.string.click_to_delete))
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -200,6 +216,11 @@ class ThemeConfigFragment : PreferenceFragmentCompat(),
//recreateActivities()
}
PreferKey.colorImage ->
Handler(Looper.getMainLooper()).postDelayed({
requireContext().restart()
}, 100)
PreferKey.bgImage,
PreferKey.bgImageN -> {
upPreferenceSummary(key, getPrefString(key))
@@ -232,6 +253,8 @@ class ThemeConfigFragment : PreferenceFragmentCompat(),
PreferKey.bgImage -> selectBgAction(false)
PreferKey.bgImageN -> selectBgAction(true)
"colorImage" -> selectBgAction(null)
"themeList" -> ThemeListDialog().show(childFragmentManager, "themeList")
"saveDayTheme",
"saveNightTheme" -> alertSaveTheme(key)
@@ -267,39 +290,60 @@ class ThemeConfigFragment : PreferenceFragmentCompat(),
}
}
private fun selectBgAction(isNight: Boolean) {
val bgKey = if (isNight) PreferKey.bgImageN else PreferKey.bgImage
val blurringKey = if (isNight) PreferKey.bgImageNBlurring else PreferKey.bgImageBlurring
val actions = arrayListOf(
getString(R.string.background_image_blurring),
getString(R.string.select_image)
)
if (!getPrefString(bgKey).isNullOrEmpty()) {
actions.add(getString(R.string.delete))
}
context?.selector(items = actions) { _, i ->
when (i) {
0 -> alertImageBlurring(blurringKey) {
upTheme(isNight)
}
private fun selectBgAction(isNight: Boolean?) {
val bgKey = when (isNight) {
true -> PreferKey.bgImageN
false -> PreferKey.bgImage
null -> PreferKey.colorImage
}
val blurringKey = when (isNight) {
true -> PreferKey.bgImageNBlurring
false -> PreferKey.bgImageBlurring
else -> null
}
1 -> {
if (isNight) {
selectImage.launch(requestCodeBgDark)
} else {
selectImage.launch(requestCodeBgLight)
val actions = mutableListOf<String>()
if (isNight != null) {
actions.add(getString(R.string.background_image_blurring))
}
actions.add(getString(R.string.select_image))
if (!getPrefString(bgKey).isNullOrEmpty()) {
actions.add(getString(R.string.delete))
}
context?.selector(items = actions) { _, i ->
when {
isNight != null && i == 0 -> {
alertImageBlurring(blurringKey!!) {
upTheme(isNight)
}
}
}
2 -> {
removePref(bgKey)
upTheme(isNight)
(isNight == null && i == 0) || (isNight != null && i == 1) -> {
when (isNight) {
true -> selectImage.launch(requestCodeBgDark)
false -> selectImage.launch(requestCodeBgLight)
null -> selectImage.launch(requestCodeColorImage)
}
}
(isNight == null && i == 1) || (isNight != null && i == 2) -> {
removePref(bgKey)
if (isNight != null) {
upTheme(isNight)
} else {
upPreferenceSummary(PreferKey.colorImage, getPrefString(PreferKey.colorImage))
}
}
}
}
}
}
private fun alertImageBlurring(preferKey: String, success: () -> Unit) {
private fun alertImageBlurring(preferKey: String, success: () -> Unit) {
alert(R.string.background_image_blurring) {
val alertBinding = DialogImageBlurringBinding.inflate(layoutInflater).apply {
getPrefInt(preferKey, 0).let {