feat: 部分设置页面的 MD3E 适配

This commit is contained in:
Super12138 2025-11-09 22:22:24 +08:00
parent a7311bfddf
commit 3b84fcd1f0
20 changed files with 115 additions and 69 deletions

View file

@ -37,7 +37,7 @@ android {
applicationId = "cn.super12138.todo"
minSdk = 24
targetSdk = 36
versionCode = 884
versionCode = 886
versionName = "2.3.3"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

View file

@ -6,7 +6,12 @@ object TodoDefaults {
/**
* 屏幕左右两边预留边距防止内容全部贴边显示过丑
*/
val screenPadding = 16.dp
val screenHorizontalPadding = 16.dp
/**
* 屏幕上下预留边距防止内容全部贴边显示过丑
*/
val screenVerticalPadding = 16.dp
/**
* 待办卡片默认高度

View file

@ -7,10 +7,13 @@ import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.FabPosition
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.LargeTopAppBar
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.material3.Text
@ -33,7 +36,7 @@ import cn.super12138.todo.utils.VibrationUtils
* @param onBack 当返回按钮被按下时的操作
* @param contentWindowInsets 内容边距通常用于将内容和系统状态栏等隔开可以使用 `WindowInsets.safeContent`
*/
@OptIn(ExperimentalMaterial3Api::class)
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
@Composable
fun LargeTopAppBarScaffold(
modifier: Modifier = Modifier,
@ -56,7 +59,9 @@ fun LargeTopAppBarScaffold(
)
},
navigationIcon = {
IconButton(
FilledIconButton(
colors = IconButtonDefaults.filledIconButtonColors(containerColor = MaterialTheme.colorScheme.surfaceContainerHigh),
shapes = IconButtonDefaults.shapes(),
onClick = {
VibrationUtils.performHapticFeedback(view)
onBack()

View file

@ -114,7 +114,7 @@ fun CrashPage(
Column(
modifier = Modifier
.padding(innerPadding)
.padding(horizontal = TodoDefaults.screenPadding)
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
.fillMaxSize()
.verticalScroll(scrollState)
) {

View file

@ -169,7 +169,7 @@ fun TodoEditorPage(
verticalArrangement = Arrangement.spacedBy(5.dp),
modifier = Modifier
.padding(innerPadding)
.padding(horizontal = TodoDefaults.screenPadding)
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
.fillMaxSize()
) {
item {

View file

@ -41,9 +41,9 @@ fun ManagerFragment(
LazyColumn(
state = state,
contentPadding = PaddingValues(
start = TodoDefaults.screenPadding,
start = TodoDefaults.screenHorizontalPadding,
bottom = TodoDefaults.toDoCardHeight / 2,
end = TodoDefaults.screenPadding
end = TodoDefaults.screenHorizontalPadding
),
/*modifier = Modifier
.clip(

View file

@ -2,9 +2,11 @@ package cn.super12138.todo.ui.pages.settings
import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Balance
import androidx.compose.material.icons.outlined.DeveloperMode
@ -12,7 +14,6 @@ import androidx.compose.material.icons.outlined.Numbers
import androidx.compose.material.icons.outlined.Person4
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@ -22,7 +23,6 @@ import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
@ -33,6 +33,7 @@ import cn.super12138.todo.constants.Constants
import cn.super12138.todo.ui.TodoDefaults
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
import cn.super12138.todo.ui.icons.GitHubIcon
import cn.super12138.todo.ui.pages.settings.components.Settings
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
import cn.super12138.todo.utils.SystemUtils
import kotlinx.coroutines.delay
@ -56,15 +57,15 @@ fun SettingsAbout(
val context = LocalContext.current
val uriHandler = LocalUriHandler.current
LazyColumn(
Column(
verticalArrangement = Arrangement.spacedBy(2.dp),
modifier = Modifier
.fillMaxWidth()
.fillMaxSize()
.padding(innerPadding)
.padding(horizontal = TodoDefaults.screenPadding)
.clip(MaterialTheme.shapes.extraExtraLarge)
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
.verticalScroll(rememberScrollState())
) {
item {
Settings {
var clickCount by remember { mutableIntStateOf(0) }
var lastClickTime by remember { mutableLongStateOf(0L) }
@ -96,32 +97,24 @@ fun SettingsAbout(
}
}
)
}
item {
SettingsItem(
leadingIcon = Icons.Outlined.Person4,
title = stringResource(R.string.pref_developer),
description = stringResource(R.string.developer_name),
onClick = { uriHandler.openUri(Constants.DEVELOPER_GITHUB) }
)
}
item {
SettingsItem(
leadingIcon = GitHubIcon,
title = stringResource(R.string.pref_view_on_github),
description = stringResource(R.string.pref_view_on_github_desc),
onClick = { uriHandler.openUri(Constants.GITHUB_REPO) }
)
}
item {
SettingsItem(
leadingIcon = Icons.Outlined.Balance,
title = stringResource(R.string.pref_licence),
description = stringResource(R.string.pref_licence_desc),
onClick = toLicencePage
)
}
item {
SettingsItem(
leadingIcon = Icons.Outlined.DeveloperMode,
title = stringResource(R.string.pref_developer_options),

View file

@ -1,16 +1,20 @@
package cn.super12138.todo.ui.pages.settings
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
import cn.super12138.todo.R
import cn.super12138.todo.ui.TodoDefaults
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
import cn.super12138.todo.ui.pages.settings.components.licence.LicenceList
import com.mikepenz.aboutlibraries.ui.compose.android.produceLibraries
@ -29,10 +33,17 @@ fun SettingsAboutLicence(
modifier = modifier
) { innerPadding ->
val libraries by produceLibraries(R.raw.aboutlibraries)
Column(
Box(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize()
.padding(innerPadding)
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
.clip(
MaterialTheme.shapes.extraLarge.copy(
bottomEnd = CornerSize(0f),
bottomStart = CornerSize(0f)
)
)
) {
val listState = rememberLazyListState()
LicenceList(

View file

@ -19,7 +19,9 @@ import androidx.compose.ui.res.stringResource
import cn.super12138.todo.R
import cn.super12138.todo.constants.Constants
import cn.super12138.todo.logic.datastore.DataStoreManager
import cn.super12138.todo.ui.TodoDefaults
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
import cn.super12138.todo.ui.pages.settings.components.Settings
import cn.super12138.todo.ui.pages.settings.components.SwitchSettingsItem
import cn.super12138.todo.ui.pages.settings.components.appearance.contrast.ContrastPicker
import cn.super12138.todo.ui.pages.settings.components.appearance.darkmode.DarkModePicker
@ -52,33 +54,36 @@ fun SettingsAppearance(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
.verticalScroll(rememberScrollState())
) {
SwitchSettingsItem(
checked = dynamicColor,
leadingIcon = Icons.Outlined.AutoAwesome,
title = stringResource(R.string.pref_appearance_dynamic_color),
description = stringResource(R.string.pref_appearance_dynamic_color_desc),
onCheckedChange = { scope.launch { DataStoreManager.setDynamicColor(it) } },
)
Settings {
SwitchSettingsItem(
checked = dynamicColor,
leadingIcon = Icons.Outlined.AutoAwesome,
title = stringResource(R.string.pref_appearance_dynamic_color),
description = stringResource(R.string.pref_appearance_dynamic_color_desc),
onCheckedChange = { scope.launch { DataStoreManager.setDynamicColor(it) } },
)
DarkModePicker(
currentDarkMode = { DarkMode.fromId(darkMode) },
onDarkModeChange = { scope.launch { DataStoreManager.setDarkMode(it.id) } }
)
DarkModePicker(
currentDarkMode = { DarkMode.fromId(darkMode) },
onDarkModeChange = { scope.launch { DataStoreManager.setDarkMode(it.id) } }
)
PalettePicker(
currentPalette = { PaletteStyle.fromId(paletteStyle) },
onPaletteChange = { scope.launch { DataStoreManager.setPaletteStyle(it.id) } },
isDynamicColor = dynamicColor,
isDarkMode = DarkMode.fromId(darkMode),
contrastLevel = ContrastLevel.fromFloat(contrastLevel)
)
PalettePicker(
currentPalette = { PaletteStyle.fromId(paletteStyle) },
onPaletteChange = { scope.launch { DataStoreManager.setPaletteStyle(it.id) } },
isDynamicColor = dynamicColor,
isDarkMode = DarkMode.fromId(darkMode),
contrastLevel = ContrastLevel.fromFloat(contrastLevel)
)
ContrastPicker(
currentContrast = ContrastLevel.fromFloat(contrastLevel),
onContrastChange = { scope.launch { DataStoreManager.setContrastLevel(it.value) } }
)
ContrastPicker(
currentContrast = ContrastLevel.fromFloat(contrastLevel),
onContrastChange = { scope.launch { DataStoreManager.setContrastLevel(it.value) } }
)
}
}
}
}

View file

@ -120,7 +120,7 @@ fun SettingsData(
Modifier
.fillMaxSize()
.padding(innerPadding)
.padding(horizontal = TodoDefaults.screenPadding)
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
.verticalScroll(rememberScrollState())
) {
SettingsCategory(stringResource(R.string.pref_category_data_management))

View file

@ -1,8 +1,10 @@
package cn.super12138.todo.ui.pages.settings
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Padding
import androidx.compose.material3.ExperimentalMaterial3Api
@ -12,7 +14,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import cn.super12138.todo.R
import cn.super12138.todo.ui.TodoDefaults
import cn.super12138.todo.ui.components.LargeTopAppBarScaffold
import cn.super12138.todo.ui.pages.settings.components.Settings
import cn.super12138.todo.ui.pages.settings.components.SettingsItem
@OptIn(ExperimentalMaterial3Api::class)
@ -29,12 +33,14 @@ fun SettingsDeveloperOptions(
scrollBehavior = scrollBehavior,
modifier = modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
) { innerPadding ->
LazyColumn(
Column(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
.padding(horizontal = TodoDefaults.screenHorizontalPadding,)
.verticalScroll(rememberScrollState())
) {
item {
Settings {
SettingsItem(
leadingIcon = Icons.Outlined.Padding,
title = stringResource(R.string.pref_padding),

View file

@ -65,7 +65,7 @@ fun SettingsInterface(
Modifier
.fillMaxSize()
.padding(innerPadding)
.padding(horizontal = TodoDefaults.screenPadding)
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
.verticalScroll(rememberScrollState())
) {
SettingsCategory(stringResource(R.string.pref_category_todo_list))

View file

@ -44,7 +44,7 @@ fun SettingsMain(
Modifier
.fillMaxSize()
.padding(innerPadding)
.padding(horizontal = TodoDefaults.screenPadding)
.padding(horizontal = TodoDefaults.screenHorizontalPadding)
.verticalScroll(rememberScrollState())
) {
Settings {

View file

@ -1,6 +1,7 @@
package cn.super12138.todo.ui.pages.settings.components
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@ -40,7 +41,8 @@ fun RowSettingsItem(
title: String,
description: String? = null,
trailingContent: (@Composable () -> Unit)? = null,
shape: Shape = MaterialTheme.shapes.large,
shape: Shape = MaterialTheme.shapes.small,
background: Color = MaterialTheme.colorScheme.surfaceContainerHigh,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
verticalAlignment: Alignment.Vertical = Alignment.Top,
scrollState: ScrollState = rememberScrollState(),
@ -54,6 +56,7 @@ fun RowSettingsItem(
description = description,
trailingContent = trailingContent,
shape = shape,
background = background,
modifier = modifier
) {
Row(
@ -91,7 +94,8 @@ fun LazyRowSettingsItem(
title: String,
description: String? = null,
trailingContent: (@Composable () -> Unit)? = null,
shape: Shape = MaterialTheme.shapes.large,
shape: Shape = MaterialTheme.shapes.small,
background: Color = MaterialTheme.colorScheme.surfaceContainerHigh,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
verticalAlignment: Alignment.Vertical = Alignment.Top,
fadedEdgeWidth: Dp,
@ -104,6 +108,7 @@ fun LazyRowSettingsItem(
description = description,
trailingContent = trailingContent,
shape = shape,
background = background,
modifier = modifier
) {
LazyRow(
@ -140,7 +145,8 @@ fun MoreContentSettingsItem(
title: String,
description: String? = null,
trailingContent: (@Composable () -> Unit)? = null,
shape: Shape = MaterialTheme.shapes.large,
shape: Shape = MaterialTheme.shapes.small,
background: Color = MaterialTheme.colorScheme.surfaceContainerHigh,
content: @Composable () -> Unit
) {
Column(
@ -148,6 +154,7 @@ fun MoreContentSettingsItem(
.fillMaxWidth()
.wrapContentHeight()
.clip(shape)
.background(background)
.padding(
horizontal = TodoDefaults.settingsItemHorizontalPadding,
vertical = TodoDefaults.settingsItemVerticalPadding

View file

@ -21,7 +21,8 @@ fun SettingsCategory(
.padding(
top = TodoDefaults.settingsItemVerticalPadding / 2,
start = TodoDefaults.settingsItemHorizontalPadding,
end = TodoDefaults.settingsItemHorizontalPadding
end = TodoDefaults.settingsItemHorizontalPadding,
bottom = TodoDefaults.settingsItemVerticalPadding / 4,
)
) {
Text(

View file

@ -3,12 +3,15 @@ package cn.super12138.todo.ui.pages.settings.components
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp
import cn.super12138.todo.ui.TodoDefaults
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable
@ -18,7 +21,10 @@ fun Settings(
) {
Column(
verticalArrangement = Arrangement.spacedBy(2.dp),
modifier = modifier.clip(MaterialTheme.shapes.extraExtraLarge),
modifier = modifier
.padding(vertical = TodoDefaults.screenVerticalPadding).clip(
shape = MaterialTheme.shapes.extraLarge
),
content = content
)
}

View file

@ -81,7 +81,7 @@ fun RadioItem(
},
role = Role.RadioButton
)
.padding(horizontal = TodoDefaults.screenPadding),
.padding(horizontal = TodoDefaults.screenHorizontalPadding),
verticalAlignment = Alignment.CenterVertically
) {
RadioButton(

View file

@ -51,7 +51,7 @@ fun SettingsItem(
title: String,
description: String? = null,
trailingContent: (@Composable () -> Unit)? = null,
background: Color = MaterialTheme.colorScheme.surfaceContainerHighest,
background: Color = MaterialTheme.colorScheme.surfaceContainerHigh,
enableClick: Boolean = true,
onClick: () -> Unit = {}
) {
@ -85,7 +85,7 @@ fun SettingsItem(
description: String? = null,
trailingContent: (@Composable () -> Unit)? = null,
shape: Shape = MaterialTheme.shapes.small,
background: Color = MaterialTheme.colorScheme.surfaceContainerHighest,
background: Color = MaterialTheme.colorScheme.surfaceContainerHigh,
enableClick: Boolean = true,
onClick: () -> Unit = {},
) {

View file

@ -1,5 +1,6 @@
package cn.super12138.todo.ui.pages.settings.components.licence
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@ -34,11 +35,13 @@ fun LicenceItem(
showAuthor: Boolean = true,
showVersion: Boolean = true,
showLicenseBadges: Boolean = true,
colors: LibraryColors = LibraryDefaults.libraryColors(),
colors: LibraryColors = LibraryDefaults.libraryColors(
libraryBackgroundColor = MaterialTheme.colorScheme.surfaceContainerHigh
),
padding: LibraryPadding = LibraryDefaults.libraryPadding(),
libraryPadding: LibraryPadding = LibraryDefaults.libraryPadding(),
typography: Typography = MaterialTheme.typography,
shape: Shape = MaterialTheme.shapes.large,
shape: Shape = MaterialTheme.shapes.small,
onClick: () -> Unit
) {
Column(
@ -46,6 +49,7 @@ fun LicenceItem(
.fillMaxWidth()
.clip(shape)
.clickable { onClick.invoke() }
.background(colors.libraryBackgroundColor)
.padding(libraryPadding.contentPadding)
) {
Row(
@ -64,7 +68,7 @@ fun LicenceItem(
val version = library.artifactVersion
if (version != null && showVersion) {
Text(
version,
text = version,
modifier = Modifier.padding(padding.versionPadding.contentPadding),
style = typography.bodyMedium,
textAlign = TextAlign.Center

View file

@ -1,5 +1,6 @@
package cn.super12138.todo.ui.pages.settings.components.licence
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
@ -21,6 +22,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import cn.super12138.todo.R
import cn.super12138.todo.ui.components.BasicDialog
import cn.super12138.todo.ui.components.LazyColumnCustomScrollBar
@ -44,9 +46,10 @@ fun LicenceList(
) {
LazyColumn(
state = state,
verticalArrangement = Arrangement.spacedBy(2.dp),
modifier = modifier
) {
items(libraries?.libraries ?: listOf()) { library ->
items(items = libraries?.libraries ?: listOf(), key = { it.artifactId }) { library ->
var openDialog by rememberSaveable { mutableStateOf(false) }
LicenceItem(