[优化] 优化了一些界面布局

This commit is contained in:
HapeLee committed 2025-12-28 15:53:32 +08:00
1 parent 841c3df172
commit 925c7ad913
9 files changed
+149 -201

No files matched your search

@@ -45,6 +45,7 @@ abstract class BaseComposeActivity(
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setupSystemBar()
// Compose 入口 // Compose 入口
setContent { setContent {
AppTheme { AppTheme {
@@ -54,8 +55,6 @@ abstract class BaseComposeActivity(
} }
} }
setupSystemBar()
if (imageBg) { if (imageBg) {
upBackgroundImage() upBackgroundImage()
} }
@@ -43,6 +43,7 @@ class AboutActivity : BaseComposeActivity() {
@Composable @Composable
override fun Content() { override fun Content() {
AboutScreen( AboutScreen(
onBack = { finish() },
onCheckUpdate = { checkUpdate() }, onCheckUpdate = { checkUpdate() },
onOpenUrl = { openUrl(it) }, onOpenUrl = { openUrl(it) },
onShowMdFile = { title, file -> showMdFile(title, file) }, onShowMdFile = { title, file -> showMdFile(title, file) },
@@ -1,6 +1,5 @@
package io.legado.app.ui.about package io.legado.app.ui.about
import android.content.res.Configuration
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
@@ -25,7 +24,6 @@ import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.MediumTopAppBar import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@@ -36,11 +34,9 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.AppTheme
import io.legado.app.constant.AppConst.appInfo import io.legado.app.constant.AppConst.appInfo
import io.legado.app.ui.widget.components.SettingItem import io.legado.app.ui.widget.components.SettingItem
import io.legado.app.ui.widget.components.SplicedColumnGroup import io.legado.app.ui.widget.components.SplicedColumnGroup
@@ -50,7 +46,7 @@ import io.legado.app.ui.widget.components.TextCard
@Composable @Composable
fun AboutScreen( fun AboutScreen(
versionName: String = appInfo.versionName, versionName: String = appInfo.versionName,
onNavigateBack: () -> Unit = {}, onBack: () -> Unit = {},
onCheckUpdate: () -> Unit = {}, onCheckUpdate: () -> Unit = {},
onOpenUrl: (String) -> Unit = {}, onOpenUrl: (String) -> Unit = {},
onShowMdFile: (String, String) -> Unit = { _, _ -> }, onShowMdFile: (String, String) -> Unit = { _, _ -> },
@@ -68,7 +64,7 @@ fun AboutScreen(
MediumTopAppBar( MediumTopAppBar(
title = { Text(stringResource(R.string.about)) }, title = { Text(stringResource(R.string.about)) },
navigationIcon = { navigationIcon = {
IconButton(onClick = onNavigateBack) { IconButton(onClick = onBack) {
Icon( Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack, imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = stringResource(R.string.back) contentDescription = stringResource(R.string.back)
@@ -82,7 +78,6 @@ fun AboutScreen(
Column( Column(
modifier = Modifier modifier = Modifier
.padding(padding) .padding(padding)
.padding(horizontal = 16.dp)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
) { ) {
Image( Image(
@@ -145,63 +140,60 @@ fun AboutScreen(
} }
SplicedColumnGroup( SplicedColumnGroup(
title = "", modifier = Modifier.padding(horizontal = 16.dp),
content = listOf( title = ""
{ ){
SettingItem( SettingItem(
modifier = Modifier.background(colorScheme.surfaceBright), title = stringResource(R.string.contributors),
title = stringResource(R.string.contributors), description = null,
description = null, option = null,
option = null, onClick = {
onClick = { onOpenUrl("https://github.com/gedoor/legado/graphs/contributors")
onOpenUrl("https://github.com/gedoor/legado/graphs/contributors")
}
)
SettingItem(
title = stringResource(R.string.privacy_policy),
description = null,
option = null,
onClick = {
onShowMdFile("隐私政策", "privacyPolicy.md")
}
)
SettingItem(
title = stringResource(R.string.license),
description = null,
option = null,
onClick = {
onShowMdFile("许可证", "LICENSE.md")
}
)
SettingItem(
title = stringResource(R.string.disclaimer),
description = null,
option = null,
onClick = {
onShowMdFile("免责声明", "disclaimer.md")
}
)
SettingItem(
title = stringResource(R.string.crash_log),
description = null,
option = null,
onClick = onShowCrashLogs
)
SettingItem(
title = stringResource(R.string.save_log),
description = null,
option = null,
onClick = onSaveLog
)
SettingItem(
title = stringResource(R.string.create_heap_dump),
description = null,
option = null,
onClick = onCreateHeapDump
)
} }
) )
) SettingItem(
title = stringResource(R.string.privacy_policy),
description = null,
option = null,
onClick = {
onShowMdFile("隐私政策", "privacyPolicy.md")
}
)
SettingItem(
title = stringResource(R.string.license),
description = null,
option = null,
onClick = {
onShowMdFile("许可证", "LICENSE.md")
}
)
SettingItem(
title = stringResource(R.string.disclaimer),
description = null,
option = null,
onClick = {
onShowMdFile("免责声明", "disclaimer.md")
}
)
SettingItem(
title = stringResource(R.string.crash_log),
description = null,
option = null,
onClick = onShowCrashLogs
)
SettingItem(
title = stringResource(R.string.save_log),
description = null,
option = null,
onClick = onSaveLog
)
SettingItem(
title = stringResource(R.string.create_heap_dump),
description = null,
option = null,
onClick = onCreateHeapDump
)
}
} }
} }
} }
@@ -1,9 +1,9 @@
package io.legado.app.ui.book.readRecord package io.legado.app.ui.book.readRecord
import android.os.Bundle import android.os.Bundle
import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import io.legado.app.base.AppTheme
import io.legado.app.data.appDb import io.legado.app.data.appDb
import io.legado.app.utils.startActivityForBook import io.legado.app.utils.startActivityForBook
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -22,10 +22,8 @@ class ReadRecordActivity : BaseComposeActivity() {
@Composable @Composable
override fun Content() { override fun Content() {
MaterialTheme { AppTheme {
val viewModel: ReadRecordViewModel = koinViewModel()
ReadRecordScreen( ReadRecordScreen(
viewModel = viewModel,
onBackClick = { finish() }, onBackClick = { finish() },
onBookClick = { bookName -> onBookClick = { bookName ->
lifecycleScope.launch { lifecycleScope.launch {
@@ -66,6 +66,7 @@ import io.legado.app.ui.widget.components.SearchBarSection
import io.legado.app.ui.widget.components.SectionHeader import io.legado.app.ui.widget.components.SectionHeader
import io.legado.app.utils.StringUtils.formatFriendlyDate import io.legado.app.utils.StringUtils.formatFriendlyDate
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import org.koin.androidx.compose.koinViewModel
import java.time.LocalDate import java.time.LocalDate
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.util.Date import java.util.Date
@@ -78,7 +79,7 @@ import kotlin.collections.sumOf
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun ReadRecordScreen( fun ReadRecordScreen(
viewModel: ReadRecordViewModel, viewModel: ReadRecordViewModel = koinViewModel(),
onBackClick: () -> Unit, onBackClick: () -> Unit,
onBookClick: (String) -> Unit onBookClick: (String) -> Unit
) { ) {
@@ -3,17 +3,21 @@ package io.legado.app.ui.replace
import android.os.Bundle import android.os.Bundle
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.Composable
import io.legado.app.base.AppTheme import io.legado.app.base.AppTheme
import io.legado.app.base.BaseComposeActivity
class ReplaceRuleActivity : AppCompatActivity() { class ReplaceRuleActivity : BaseComposeActivity() {
override fun onCreate(savedInstanceState: Bundle?) { @Composable
super.onCreate(savedInstanceState) override fun Content() {
setContent { AppTheme {
AppTheme { ReplaceRuleScreen(onBackClick = { finish() })
ReplaceRuleScreen(onBackClick = { finish() })
}
} }
} }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
} }
@@ -330,15 +330,15 @@ fun ReplaceRuleScreen(
snackbarHost = { SnackbarHost(snackbarHostState) }, snackbarHost = { SnackbarHost(snackbarHostState) },
topBar = { topBar = {
Column { Column {
val titleText = remember(isUploading, inSelectionMode, selectedRuleIds.size, rules.size) {
when {
isUploading -> "正在上传..."
inSelectionMode -> "已选择 ${selectedRuleIds.size}/${rules.size}"
else -> "替换规则"
}
}
MediumTopAppBar( MediumTopAppBar(
title = { title = {
val titleText = remember(isUploading, inSelectionMode, selectedRuleIds.size, rules.size) {
when {
isUploading -> "正在上传..."
inSelectionMode -> "已选择 ${selectedRuleIds.size}/${rules.size}"
else -> "替换规则"
}
}
AnimatedText( AnimatedText(
text = titleText text = titleText
) )
@@ -485,12 +485,12 @@ fun ReplaceRuleScreen(
) { padding -> ) { padding ->
Box( Box(
modifier = Modifier modifier = Modifier
.padding(padding)
.fillMaxSize() .fillMaxSize()
) { ) {
FastScrollLazyColumn( FastScrollLazyColumn(
state = listState, state = listState,
modifier = Modifier modifier = Modifier
.padding(padding)
.fillMaxSize(), .fillMaxSize(),
contentPadding = PaddingValues( contentPadding = PaddingValues(
top = 8.dp, top = 8.dp,
@@ -561,7 +561,6 @@ fun ReplaceRuleScreen(
onSelectionChange = viewModel::setSelection, onSelectionChange = viewModel::setSelection,
haptic = haptic, haptic = haptic,
modifier = Modifier modifier = Modifier
.padding(padding)
.fillMaxHeight() .fillMaxHeight()
.width(60.dp) .width(60.dp)
.align(Alignment.TopStart) .align(Alignment.TopStart)
@@ -1,5 +1,6 @@
package io.legado.app.ui.widget.components package io.legado.app.ui.widget.components
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@@ -15,6 +16,8 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ChevronRight import androidx.compose.material.icons.filled.ChevronRight
import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.Info
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MaterialTheme.colorScheme import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
@@ -95,85 +98,64 @@ fun SettingItem(
painter: Painter? = null, painter: Painter? = null,
imageVector: ImageVector? = null, imageVector: ImageVector? = null,
title: String, title: String,
description: String? = null,
option: String? = null, option: String? = null,
trailingContent: @Composable (() -> Unit)? = null, trailingContent: @Composable (() -> Unit)? = null,
description: String? = null,
onClick: () -> Unit onClick: () -> Unit
) { ) {
Row( ListItem(
modifier = Modifier modifier = modifier
.clip(RoundedCornerShape(4.dp)) .clip(RoundedCornerShape(4.dp))
.then(modifier) .clickable(onClick = onClick),
.fillMaxWidth() leadingContent = {
.clickable { onClick() } when {
.padding(horizontal = 8.dp) painter != null -> {
.padding(vertical = 12.dp) Icon(
.heightIn(min = 56.dp), painter = painter,
verticalAlignment = Alignment.CenterVertically contentDescription = null,
) { tint = MaterialTheme.colorScheme.onSurfaceVariant
)
painter?.let { }
Icon(
modifier = Modifier.padding(end = 8.dp).size(24.dp),
painter = it,
tint = colorScheme.onSurfaceVariant,
contentDescription = "Icon"
)
}
imageVector?.let {
Icon(
imageVector = it,
contentDescription = null,
modifier = Modifier
.padding(end = 8.dp)
.size(24.dp),
tint = colorScheme.onSurfaceVariant
)
}
Column(
modifier = Modifier.weight(1f),
verticalArrangement = if (description == null)
Arrangement.Center
else
Arrangement.spacedBy(3.dp)
) {
imageVector != null -> {
Icon(
imageVector = imageVector,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
},
headlineContent = {
Text( Text(
text = title, text = title,
color = colorScheme.onSurface, style = MaterialTheme.typography.titleMedium
style = AppTypography.titleMedium,
fontWeight = FontWeight.Normal
) )
},
supportingContent = {
Column(verticalArrangement = Arrangement.spacedBy(2.dp)) {
description?.let {
Text(
text = it,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
description?.let { option?.let {
Text( AnimatedTextLine(
text = it, text = it,
color = colorScheme.onSurfaceVariant, style = MaterialTheme.typography.labelMedium,
style = AppTypography.labelMedium color = MaterialTheme.colorScheme.primary,
) maxLines = 3,
overflow = TextOverflow.Ellipsis
)
}
} }
},
option?.let { trailingContent = trailingContent,
AnimatedTextLine( colors = ListItemDefaults.colors(
text = it, containerColor = MaterialTheme.colorScheme.surfaceContainerLow
style = AppTypography.labelMedium, )
color = colorScheme.primary, )
maxLines = 3,
overflow = TextOverflow.Ellipsis
)
}
}
trailingContent?.let { composable ->
Box(
modifier = Modifier
.width(55.dp),
contentAlignment = Alignment.Center
) {
composable()
}
}
}
} }
@@ -3,8 +3,12 @@ package io.legado.app.ui.widget.components
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -14,7 +18,7 @@ import androidx.compose.ui.unit.dp
/** /**
* Settings Group Container by https://github.com/wxxsfxyzm/InstallerX-Revived * Settings Group Container by https://github.com/wxxsfxyzm/InstallerX-Revived
* * Edit by @Kudomaga
* @param title the title of the group * @param title the title of the group
* @param content a list of composable that will be displayed in the group * @param content a list of composable that will be displayed in the group
* @param modifier Modifier * @param modifier Modifier
@@ -23,61 +27,29 @@ import androidx.compose.ui.unit.dp
fun SplicedColumnGroup( fun SplicedColumnGroup(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
title: String = "", title: String = "",
content: List<@Composable () -> Unit>, content: @Composable ColumnScope.() -> Unit,
) { ) {
if (content.isEmpty()) return
val cornerRadius = 16.dp
val connectionRadius = 5.dp
// Define shapes for different positions.
val topShape = RoundedCornerShape(
topStart = cornerRadius,
topEnd = cornerRadius,
bottomStart = connectionRadius,
bottomEnd = connectionRadius
)
val middleShape = RoundedCornerShape(connectionRadius)
val bottomShape = RoundedCornerShape(
topStart = connectionRadius,
topEnd = connectionRadius,
bottomStart = cornerRadius,
bottomEnd = cornerRadius
)
val singleShape = RoundedCornerShape(cornerRadius)
Column(modifier = modifier.padding(vertical = 8.dp)) { Column(modifier = modifier.padding(vertical = 8.dp)) {
// Group title if (title.isNotEmpty()) {
if (title != "")
Text( Text(
text = title, text = title,
style = MaterialTheme.typography.titleSmall, style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary, color = MaterialTheme.colorScheme.primary,
modifier = Modifier.padding(start = 16.dp, bottom = 8.dp) modifier = Modifier.padding(start = 16.dp, bottom = 8.dp)
) )
}
// The container for setting items. Card(
Column( shape = RoundedCornerShape(16.dp),
modifier = Modifier.clip( colors = CardDefaults.cardColors(
// Clip the whole column to ensure content stays within the rounded bounds. containerColor = MaterialTheme.colorScheme.surface
if (content.size == 1) singleShape else RoundedCornerShape(cornerRadius)
), ),
verticalArrangement = Arrangement.spacedBy(2.dp) modifier = Modifier.fillMaxWidth()
) { ) {
content.forEachIndexed { index, itemContent -> Column(
// Determine the shape based on the pkg's position. verticalArrangement = Arrangement.spacedBy(4.dp)
val shape = when { ) {
content.size == 1 -> singleShape content()
index == 0 -> topShape
index == content.size - 1 -> bottomShape
else -> middleShape
}
// Apply background with the correct shape to the pkg.
Column(
modifier = Modifier.background(MaterialTheme.colorScheme.surfaceBright, shape)
) {
itemContent()
}
} }
} }
} }