Add application DPI setting function
- Allow users to customize the display density of the current application - Fix some popup color errors
This commit is contained in:
@@ -49,6 +49,9 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
// 应用DPI设置(仅对当前应用生效)
|
||||||
|
applyCustomDpi()
|
||||||
|
|
||||||
// Enable edge to edge
|
// Enable edge to edge
|
||||||
enableEdgeToEdge()
|
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() {
|
override fun onPause() {
|
||||||
super.onPause()
|
super.onPause()
|
||||||
CardConfig.save(applicationContext)
|
CardConfig.save(applicationContext)
|
||||||
|
|||||||
@@ -47,11 +47,7 @@ fun SlotSelectionDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (show) {
|
if (show) {
|
||||||
val cardColor = if (!ThemeConfig.useDynamicColor) {
|
val cardColor = MaterialTheme.colorScheme.surfaceContainerHighest
|
||||||
ThemeConfig.currentTheme.ButtonContrast
|
|
||||||
} else {
|
|
||||||
MaterialTheme.colorScheme.surfaceContainerHigh
|
|
||||||
}
|
|
||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.sukisu.ultra.ui.screen
|
package com.sukisu.ultra.ui.screen
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
@@ -29,6 +30,7 @@ import androidx.compose.foundation.verticalScroll
|
|||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
import androidx.compose.material.icons.automirrored.filled.NavigateNext
|
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.Brush
|
||||||
import androidx.compose.material.icons.filled.ColorLens
|
import androidx.compose.material.icons.filled.ColorLens
|
||||||
import androidx.compose.material.icons.filled.DarkMode
|
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.Destination
|
||||||
import com.ramcosta.composedestinations.annotation.RootGraph
|
import com.ramcosta.composedestinations.annotation.RootGraph
|
||||||
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
|
||||||
import com.sukisu.ultra.Natives
|
|
||||||
import com.sukisu.ultra.R
|
import com.sukisu.ultra.R
|
||||||
import com.sukisu.ultra.ksuApp
|
|
||||||
import com.sukisu.ultra.ui.component.ImageEditorDialog
|
import com.sukisu.ultra.ui.component.ImageEditorDialog
|
||||||
import com.sukisu.ultra.ui.component.KsuIsValid
|
import com.sukisu.ultra.ui.component.KsuIsValid
|
||||||
import com.sukisu.ultra.ui.component.SwitchItem
|
import com.sukisu.ultra.ui.component.SwitchItem
|
||||||
@@ -227,6 +227,36 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
|
|||||||
var isCustomizeExpanded by remember { mutableStateOf(false) }
|
var isCustomizeExpanded by remember { mutableStateOf(false) }
|
||||||
var isAppearanceExpanded by remember { mutableStateOf(true) }
|
var isAppearanceExpanded by remember { mutableStateOf(true) }
|
||||||
var isAdvancedExpanded by remember { mutableStateOf(false) }
|
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) {
|
LaunchedEffect(Unit) {
|
||||||
@@ -263,10 +293,37 @@ fun MoreSettingsScreen(navigator: DestinationsNavigator) {
|
|||||||
CardConfig.setDarkModeDefaults()
|
CardConfig.setDarkModeDefaults()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存设置
|
currentDpi = prefs.getInt("app_dpi", systemDpi)
|
||||||
|
tempDpi = currentDpi
|
||||||
|
|
||||||
CardConfig.save(context)
|
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(
|
val themeColorOptions = listOf(
|
||||||
stringResource(R.string.color_default) to ThemeColors.Default,
|
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(
|
SectionHeader(
|
||||||
title = stringResource(R.string.custom_settings),
|
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) {
|
if (showThemeColorDialog) {
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
|
|||||||
@@ -328,4 +328,18 @@
|
|||||||
<string name="use_webuix_summary">使用支持更多 API 的 WebUI X 而不是 WebUI</string>
|
<string name="use_webuix_summary">使用支持更多 API 的 WebUI X 而不是 WebUI</string>
|
||||||
<string name="use_webuix_eruda">将 Eruda 注入 WebUI X</string>
|
<string name="use_webuix_eruda">将 Eruda 注入 WebUI X</string>
|
||||||
<string name="use_webuix_eruda_summary">在 WebUI X 中注入调试控制台,使调试更容易,需要启用 WebView 调试</string>
|
<string name="use_webuix_eruda_summary">在 WebUI X 中注入调试控制台,使调试更容易,需要启用 WebView 调试</string>
|
||||||
|
<!-- DPI设置相关字符串 -->
|
||||||
|
<string name="dpi_settings">DPI 设置</string>
|
||||||
|
<string name="app_dpi_title">应用DPI</string>
|
||||||
|
<string name="app_dpi_summary">仅调整当前应用的屏幕显示密度</string>
|
||||||
|
<string name="dpi_size_small">小</string>
|
||||||
|
<string name="dpi_size_medium">中</string>
|
||||||
|
<string name="dpi_size_large">大</string>
|
||||||
|
<string name="dpi_size_extra_large">超大</string>
|
||||||
|
<string name="dpi_size_custom">自定义</string>
|
||||||
|
<string name="dpi_apply_settings">应用DPI设置</string>
|
||||||
|
<string name="dpi_confirm_title">确认更改DPI</string>
|
||||||
|
<string name="dpi_confirm_message">你确定要将应用DPI从 %1$d 更改为 %2$d 吗?</string>
|
||||||
|
<string name="dpi_confirm_summary">应用需要重启以应用新的DPI设置,不会影响系统状态栏或其他应用</string>
|
||||||
|
<string name="dpi_applied_success">DPI 已设置为 %1$d,重启应用后生效</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -332,4 +332,18 @@
|
|||||||
<string name="use_webuix_summary">Use WebUI X instead of WebUI which supports more API\'s</string>
|
<string name="use_webuix_summary">Use WebUI X instead of WebUI which supports more API\'s</string>
|
||||||
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
|
<string name="use_webuix_eruda">Inject Eruda into WebUI X</string>
|
||||||
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
|
<string name="use_webuix_eruda_summary">Inject a debug console into WebUI X to make debugging easier. Requires web debugging to be on.</string>
|
||||||
|
<!-- DPI setting related strings -->
|
||||||
|
<string name="dpi_settings">DPI setting</string>
|
||||||
|
<string name="app_dpi_title">Applied DPI</string>
|
||||||
|
<string name="app_dpi_summary">Adjust the screen display density for the current application only</string>
|
||||||
|
<string name="dpi_size_small">Small </string>
|
||||||
|
<string name="dpi_size_medium">Medium </string>
|
||||||
|
<string name="dpi_size_large">Big</string>
|
||||||
|
<string name="dpi_size_extra_large">oversize</string>
|
||||||
|
<string name="dpi_size_custom">customizable</string>
|
||||||
|
<string name="dpi_apply_settings">Applying DPI settings</string>
|
||||||
|
<string name="dpi_confirm_title">Confirm DPI change</string>
|
||||||
|
<string name="dpi_confirm_message">Are you sure you want to change the application DPI from %1$d to %2$d?</string>
|
||||||
|
<string name="dpi_confirm_summary">Application needs to be restarted to apply the new DPI settings, does not affect the system status bar or other applications</string>
|
||||||
|
<string name="dpi_applied_success">DPI has been set to %1$d, effective after restarting the application</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user