From 3d0d87cb0cdc6d1a508506be4614a339e5847f7c Mon Sep 17 00:00:00 2001
From: ShirkNeko <109797057+ShirkNeko@users.noreply.github.com>
Date: Tue, 13 May 2025 23:56:18 +0800
Subject: [PATCH] Add application DPI setting function
- Allow users to customize the display density of the current application
- Fix some popup color errors
---
.../java/com/sukisu/ultra/ui/MainActivity.kt | 23 ++
.../ultra/ui/component/SlotSelectionDialog.kt | 6 +-
.../sukisu/ultra/ui/screen/MoreSettings.kt | 207 +++++++++++++++++-
.../src/main/res/values-zh-rCN/strings.xml | 14 ++
manager/app/src/main/res/values/strings.xml | 14 ++
5 files changed, 256 insertions(+), 8 deletions(-)
diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/MainActivity.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/MainActivity.kt
index 96c2425c..7e08653b 100644
--- a/manager/app/src/main/java/com/sukisu/ultra/ui/MainActivity.kt
+++ b/manager/app/src/main/java/com/sukisu/ultra/ui/MainActivity.kt
@@ -49,6 +49,9 @@ class MainActivity : ComponentActivity() {
}
override fun onCreate(savedInstanceState: Bundle?) {
+ // 应用DPI设置(仅对当前应用生效)
+ applyCustomDpi()
+
// Enable edge to edge
enableEdgeToEdge()
@@ -135,6 +138,26 @@ class MainActivity : ComponentActivity() {
}
}
+ // 应用自定义DPI设置(仅对当前应用生效)
+ private fun applyCustomDpi() {
+ val prefs = getSharedPreferences("settings", MODE_PRIVATE)
+ val customDpi = prefs.getInt("app_dpi", 0)
+
+ if (customDpi > 0) {
+ try {
+ val resources = resources
+ val metrics = resources.displayMetrics
+
+ // 仅更新应用内显示,不影响系统状态栏
+ metrics.density = customDpi / 160f
+ metrics.scaledDensity = customDpi / 160f
+ metrics.densityDpi = customDpi
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+ }
+
override fun onPause() {
super.onPause()
CardConfig.save(applicationContext)
diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/component/SlotSelectionDialog.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/component/SlotSelectionDialog.kt
index db6f9e04..b4f8087d 100644
--- a/manager/app/src/main/java/com/sukisu/ultra/ui/component/SlotSelectionDialog.kt
+++ b/manager/app/src/main/java/com/sukisu/ultra/ui/component/SlotSelectionDialog.kt
@@ -47,11 +47,7 @@ fun SlotSelectionDialog(
}
if (show) {
- val cardColor = if (!ThemeConfig.useDynamicColor) {
- ThemeConfig.currentTheme.ButtonContrast
- } else {
- MaterialTheme.colorScheme.surfaceContainerHigh
- }
+ val cardColor = MaterialTheme.colorScheme.surfaceContainerHighest
AlertDialog(
onDismissRequest = onDismiss,
diff --git a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/MoreSettings.kt b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/MoreSettings.kt
index 2afb2127..40f889a5 100644
--- a/manager/app/src/main/java/com/sukisu/ultra/ui/screen/MoreSettings.kt
+++ b/manager/app/src/main/java/com/sukisu/ultra/ui/screen/MoreSettings.kt
@@ -1,6 +1,7 @@
package com.sukisu.ultra.ui.screen
import android.content.Context
+import android.content.Intent
import android.net.Uri
import android.os.Build
import android.widget.Toast
@@ -29,6 +30,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.NavigateNext
+import androidx.compose.material.icons.filled.AcUnit
import androidx.compose.material.icons.filled.Brush
import androidx.compose.material.icons.filled.ColorLens
import androidx.compose.material.icons.filled.DarkMode
@@ -81,9 +83,7 @@ import androidx.core.content.edit
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.annotation.RootGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
-import com.sukisu.ultra.Natives
import com.sukisu.ultra.R
-import com.sukisu.ultra.ksuApp
import com.sukisu.ultra.ui.component.ImageEditorDialog
import com.sukisu.ultra.ui.component.KsuIsValid
import com.sukisu.ultra.ui.component.SwitchItem
@@ -227,6 +227,36 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
var isCustomizeExpanded by remember { mutableStateOf(false) }
var isAppearanceExpanded by remember { mutableStateOf(true) }
var isAdvancedExpanded by remember { mutableStateOf(false) }
+ var isDpiExpanded by remember { mutableStateOf(false) }
+
+ // DPI 设置
+ val systemDpi = remember { context.resources.displayMetrics.densityDpi }
+ var currentDpi by remember {
+ mutableIntStateOf(prefs.getInt("app_dpi", systemDpi))
+ }
+ var tempDpi by remember { mutableIntStateOf(currentDpi) }
+ var isDpiCustom by remember { mutableStateOf(true) }
+ var showDpiConfirmDialog by remember { mutableStateOf(false) }
+
+ // 预设 DPI 选项
+ val dpiPresets = mapOf(
+ stringResource(R.string.dpi_size_small) to 240,
+ stringResource(R.string.dpi_size_medium) to 320,
+ stringResource(R.string.dpi_size_large) to 420,
+ stringResource(R.string.dpi_size_extra_large) to 560
+ )
+
+ // 获取DPI大小
+ @Composable
+ fun getDpiFriendlyName(dpi: Int): String {
+ return when (dpi) {
+ 240 -> stringResource(R.string.dpi_size_small)
+ 320 -> stringResource(R.string.dpi_size_medium)
+ 420 -> stringResource(R.string.dpi_size_large)
+ 560 -> stringResource(R.string.dpi_size_extra_large)
+ else -> stringResource(R.string.dpi_size_custom)
+ }
+ }
// 初始化卡片配置
LaunchedEffect(Unit) {
@@ -263,10 +293,37 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
CardConfig.setDarkModeDefaults()
}
- // 保存设置
+ currentDpi = prefs.getInt("app_dpi", systemDpi)
+ tempDpi = currentDpi
+
CardConfig.save(context)
}
+ // 应用 DPI 设置
+ val applyDpiSetting = { dpi: Int ->
+ if (dpi != currentDpi) {
+ // 保存到 SharedPreferences
+ prefs.edit {
+ putInt("app_dpi", dpi)
+ }
+
+ // 只修改应用级别的DPI设置
+ currentDpi = dpi
+ tempDpi = dpi
+ Toast.makeText(
+ context,
+ context.getString(R.string.dpi_applied_success, dpi),
+ Toast.LENGTH_SHORT
+ ).show()
+
+ val restartIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)
+ restartIntent?.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
+ context.startActivity(restartIntent)
+
+ showDpiConfirmDialog = false
+ }
+ }
+
// 主题色选项
val themeColorOptions = listOf(
stringResource(R.string.color_default) to ThemeColors.Default,
@@ -575,6 +632,114 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
}
}
+ // DPI 设置部分
+ SectionHeader(
+ title = stringResource(R.string.dpi_settings),
+ expanded = isDpiExpanded,
+ onToggle = { isDpiExpanded = !isDpiExpanded }
+ )
+
+ AnimatedVisibility(
+ visible = isDpiExpanded,
+ enter = fadeIn() + expandVertically(),
+ exit = fadeOut() + shrinkVertically()
+ ) {
+ Surface(
+ shape = RoundedCornerShape(16.dp),
+ tonalElevation = 1.dp,
+ modifier = Modifier.padding(bottom = 16.dp)
+ ) {
+ Column {
+ ListItem(
+ headlineContent = { Text(stringResource(R.string.app_dpi_title)) },
+ supportingContent = { Text(stringResource(R.string.app_dpi_summary)) },
+ leadingContent = {
+ Icon(
+ Icons.Default.AcUnit,
+ contentDescription = null,
+ tint = MaterialTheme.colorScheme.primary
+ )
+ },
+ trailingContent = {
+ Text(
+ text = getDpiFriendlyName(tempDpi),
+ style = MaterialTheme.typography.bodyMedium,
+ color = MaterialTheme.colorScheme.primary
+ )
+ },
+ colors = ListItemDefaults.colors(
+ containerColor = Color.Transparent
+ )
+ )
+
+ // DPI 滑动条
+ Column(modifier = Modifier.padding(horizontal = 32.dp, vertical = 8.dp)) {
+ Slider(
+ value = tempDpi.toFloat(),
+ onValueChange = {
+ tempDpi = it.toInt()
+ isDpiCustom = !dpiPresets.containsValue(tempDpi)
+ },
+ valueRange = 160f..600f,
+ steps = 11,
+ colors = SliderDefaults.colors(
+ thumbColor = MaterialTheme.colorScheme.primary,
+ activeTrackColor = MaterialTheme.colorScheme.primary,
+ inactiveTrackColor = MaterialTheme.colorScheme.surfaceVariant
+ )
+ )
+
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = 8.dp),
+ ) {
+ dpiPresets.forEach { (name, dpi) ->
+ TextButton(
+ onClick = {
+ tempDpi = dpi
+ isDpiCustom = false
+ },
+ modifier = Modifier.weight(1f)
+ ) {
+ Text(
+ text = name,
+ color = if (tempDpi == dpi)
+ MaterialTheme.colorScheme.primary
+ else
+ MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ }
+ }
+ }
+
+ TextButton(
+ onClick = {
+ if (tempDpi != currentDpi) {
+ showDpiConfirmDialog = true
+ }
+ },
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = 8.dp)
+ ) {
+ Text(stringResource(R.string.dpi_apply_settings))
+ }
+
+ Text(
+ text = if (isDpiCustom)
+ "${stringResource(R.string.dpi_size_custom)}: $tempDpi"
+ else
+ "${getDpiFriendlyName(tempDpi)}: $tempDpi",
+ style = MaterialTheme.typography.bodySmall,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.padding(top = 4.dp)
+ )
+ }
+ }
+ }
+ }
+
// 自定义设置部分
SectionHeader(
title = stringResource(R.string.custom_settings),
@@ -863,6 +1028,42 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
)
}
+ // DPI 设置确认对话框
+ if (showDpiConfirmDialog) {
+ AlertDialog(
+ onDismissRequest = { showDpiConfirmDialog = false },
+ title = { Text(stringResource(R.string.dpi_confirm_title)) },
+ text = {
+ Column {
+ Text(stringResource(R.string.dpi_confirm_message, currentDpi, tempDpi))
+ Text(
+ stringResource(R.string.dpi_confirm_summary),
+ style = MaterialTheme.typography.bodySmall,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ modifier = Modifier.padding(top = 8.dp)
+ )
+ }
+ },
+ confirmButton = {
+ TextButton(
+ onClick = { applyDpiSetting(tempDpi) }
+ ) {
+ Text(stringResource(R.string.confirm))
+ }
+ },
+ dismissButton = {
+ TextButton(
+ onClick = {
+ showDpiConfirmDialog = false
+ tempDpi = currentDpi
+ }
+ ) {
+ Text(stringResource(R.string.cancel))
+ }
+ }
+ )
+ }
+
// 主题色选择对话框
if (showThemeColorDialog) {
AlertDialog(
diff --git a/manager/app/src/main/res/values-zh-rCN/strings.xml b/manager/app/src/main/res/values-zh-rCN/strings.xml
index 61a67260..8a8fcd87 100644
--- a/manager/app/src/main/res/values-zh-rCN/strings.xml
+++ b/manager/app/src/main/res/values-zh-rCN/strings.xml
@@ -328,4 +328,18 @@
使用支持更多 API 的 WebUI X 而不是 WebUI
将 Eruda 注入 WebUI X
在 WebUI X 中注入调试控制台,使调试更容易,需要启用 WebView 调试
+
+ DPI 设置
+ 应用DPI
+ 仅调整当前应用的屏幕显示密度
+ 小
+ 中
+ 大
+ 超大
+ 自定义
+ 应用DPI设置
+ 确认更改DPI
+ 你确定要将应用DPI从 %1$d 更改为 %2$d 吗?
+ 应用需要重启以应用新的DPI设置,不会影响系统状态栏或其他应用
+ DPI 已设置为 %1$d,重启应用后生效
diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml
index 6434432e..653987c5 100644
--- a/manager/app/src/main/res/values/strings.xml
+++ b/manager/app/src/main/res/values/strings.xml
@@ -332,4 +332,18 @@
Use WebUI X instead of WebUI which supports more API\'s
Inject Eruda into WebUI X
Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.
+
+ DPI setting
+ Applied DPI
+ Adjust the screen display density for the current application only
+ Small
+ Medium
+ Big
+ oversize
+ customizable
+ Applying DPI settings
+ Confirm DPI change
+ Are you sure you want to change the application DPI from %1$d to %2$d?
+ Application needs to be restarted to apply the new DPI settings, does not affect the system status bar or other applications
+ DPI has been set to %1$d, effective after restarting the application