From b5bb7ed77ea1ee08976794129b7b0cd7a37c398e Mon Sep 17 00:00:00 2001 From: fansangg Date: Sun, 14 Jun 2026 02:40:38 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=E9=A1=B5=E7=9C=89=E9=A1=B5?= =?UTF-8?q?=E8=84=9A=E7=9A=84=E9=97=B4=E8=B7=9D=E8=AE=BE=E7=BD=AE=E7=A7=BB?= =?UTF-8?q?=E5=88=B0=E4=BF=A1=E6=81=AF=EF=BC=8C=E4=BF=A1=E6=81=AF=E6=94=B9?= =?UTF-8?q?=E6=88=90dialog=E5=BD=A2=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../app/ui/book/read/ReadBookContract.kt | 1 + .../app/ui/book/read/ReadBookMenuBar.kt | 37 +++-- .../ui/book/read/sheet/HeaderFooterPage.kt | 145 +++++++++++++++++- .../ui/book/read/sheet/PaddingConfigSheet.kt | 134 +++------------- .../app/ui/book/read/sheet/ReadStyleSheet.kt | 25 ++- .../app/ui/book/read/sheet/SystemMenuPage.kt | 2 +- 6 files changed, 196 insertions(+), 148 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookContract.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookContract.kt index 119986f5b..579608c2a 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookContract.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookContract.kt @@ -40,6 +40,7 @@ sealed interface ReadBookMenuRoute { data object ReadAloud : ReadBookMenuRoute data object AutoRead : ReadBookMenuRoute data object PaddingConfig : ReadBookMenuRoute + data object HeaderFooterConfig : ReadBookMenuRoute data class Bookmark(val bookmark: io.legado.app.data.entities.Bookmark) : ReadBookMenuRoute } diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookMenuBar.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookMenuBar.kt index 41a8c405f..dfb45706c 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookMenuBar.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookMenuBar.kt @@ -139,6 +139,7 @@ import io.legado.app.help.config.ReadStyleResolver import io.legado.app.ui.animation.DampedDragAnimation import io.legado.app.ui.animation.InteractiveHighlight import io.legado.app.ui.book.read.sheet.AutoReadContent +import io.legado.app.ui.book.read.sheet.HeaderFooterPage import io.legado.app.ui.book.read.sheet.PaddingConfigContent import io.legado.app.ui.book.read.sheet.ReadAloudContent import io.legado.app.ui.book.read.sheet.ReadMenuButtonInfo @@ -186,7 +187,7 @@ fun ReadBookMenuBar( } else { ReadBookMenuContent.Route(currentRoute) } - val dialogLikeRoute = currentRoute == ReadBookMenuRoute.PaddingConfig + val dialogLikeRoute = currentRoute == ReadBookMenuRoute.PaddingConfig || currentRoute == ReadBookMenuRoute.HeaderFooterConfig var readStylePage by remember { mutableIntStateOf(0) } LaunchedEffect(currentRoute) { if (currentRoute != ReadBookMenuRoute.ReadStyle) { @@ -392,7 +393,7 @@ private fun ReadBookMenuSurface( is ReadBookMenuContent.Route -> contentTarget.route } val expanded = route != ReadBookMenuRoute.Main - val dialogLikeRoute = route == ReadBookMenuRoute.PaddingConfig + val dialogLikeRoute = route == ReadBookMenuRoute.PaddingConfig || route == ReadBookMenuRoute.HeaderFooterConfig val density = LocalDensity.current val windowSize = LocalWindowInfo.current.containerSize var surfaceHeightPx by remember { mutableIntStateOf(0) } @@ -400,18 +401,6 @@ private fun ReadBookMenuSurface( targetValue = if (dialogLikeRoute) 1f else 0f, label = "ReadBookMenuMorph", ) - val headerFooterLift by animateDpAsState( - targetValue = if (route == ReadBookMenuRoute.ReadStyle && readStylePage == 2) { - 72.dp - } else { - 0.dp - }, - animationSpec = tween( - durationMillis = 280, - easing = LinearOutSlowInEasing, - ), - label = "ReadBookMenuHeaderFooterLift", - ) val maxHeight = with(density) { windowSize.height.toDp() * 0.64f } @@ -518,8 +507,7 @@ private fun ReadBookMenuSurface( .onSizeChanged { surfaceHeightPx = it.height } .offset { val dialogLiftPx = ((windowSize.height - surfaceHeightPx) / 2f) * morphProgress - val liftPx = dialogLiftPx + headerFooterLift.toPx() - IntOffset(x = 0, y = -liftPx.roundToInt()) + IntOffset(x = 0, y = -dialogLiftPx.roundToInt()) } .then( if (useLiquidGlass) { @@ -620,6 +608,9 @@ private fun ReadBookMenuSurface( onOpenPaddingConfig = { onIntent(ReadBookIntent.OpenReadMenuRoute(ReadBookMenuRoute.PaddingConfig)) }, + onOpenHeaderFooterConfig = { + onIntent(ReadBookIntent.OpenReadMenuRoute(ReadBookMenuRoute.HeaderFooterConfig)) + }, onOpenMoreConfig = { onIntent(ReadBookIntent.ShowSheet(ReadBookSheet.MoreConfig)) }, @@ -659,6 +650,20 @@ private fun ReadBookMenuSurface( } } + ReadBookMenuRoute.HeaderFooterConfig -> { + ReadBookMenuRoutePage( + title = stringResource(R.string.header_footer), + maxHeight = maxHeight, + scrollContent = false, + bottomPadding = if (extendSurfaceToNavigationBar) navBarHeight else 0.dp, + onBack = { onIntent(ReadBookIntent.ReadMenuBack) }, + ) { + HeaderFooterPage( + onIntent = onIntent, + ) + } + } + ReadBookMenuRoute.TextTitle -> { ReadBookMenuRoutePage( title = stringResource(R.string.read_config_text_effects), diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt index 086fefb4c..1ed7d6097 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt @@ -1,25 +1,36 @@ package io.legado.app.ui.book.read.sheet +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.FastOutSlowInEasing import androidx.compose.animation.core.tween +import androidx.compose.animation.expandVertically +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ChevronRight +import androidx.compose.material.icons.filled.ExpandMore import androidx.compose.material.icons.filled.TextFields import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.mutableStateOf @@ -41,6 +52,7 @@ import androidx.compose.ui.unit.dp import androidx.core.net.toUri import androidx.lifecycle.compose.collectAsStateWithLifecycle import io.legado.app.R +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.data.repository.ReadPreferences import io.legado.app.data.repository.ReadSettingsRepository import io.legado.app.help.config.ReadBookConfig @@ -55,6 +67,7 @@ import io.legado.app.ui.widget.components.settingItem.TinySliderSettingItem import io.legado.app.ui.widget.components.settingItem.TinySwitchSettingItem import io.legado.app.ui.widget.components.tabRow.CardTabRow import io.legado.app.utils.getCompatColor +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.koin.compose.koinInject @@ -106,6 +119,48 @@ internal fun HeaderFooterPage( var colorPickerInitial by remember { mutableIntStateOf(0) } var showFontSelect by remember { mutableStateOf(false) } + var expandHeaderPadding by remember { mutableStateOf(false) } + var expandFooterPadding by remember { mutableStateOf(false) } + + val headerScrollState = rememberScrollState() + val footerScrollState = rememberScrollState() + + LaunchedEffect(expandHeaderPadding) { + if (expandHeaderPadding) { + snapshotFlow { headerScrollState.maxValue } + .collect { maxVal -> + headerScrollState.scrollTo(maxVal) + } + } + } + + LaunchedEffect(expandFooterPadding) { + if (expandFooterPadding) { + snapshotFlow { footerScrollState.maxValue } + .collect { maxVal -> + footerScrollState.scrollTo(maxVal) + } + } + } + + DisposableEffect(Unit) { + onDispose { + onIntent(ReadBookIntent.SaveReadStyleConfig) + } + } + + // Header padding state + var headerPaddingTop by remember { mutableFloatStateOf(ReadBookConfig.headerPaddingTop.toFloat()) } + var headerPaddingBottom by remember { mutableFloatStateOf(ReadBookConfig.headerPaddingBottom.toFloat()) } + var headerPaddingLeft by remember { mutableFloatStateOf(ReadBookConfig.headerPaddingLeft.toFloat()) } + var headerPaddingRight by remember { mutableFloatStateOf(ReadBookConfig.headerPaddingRight.toFloat()) } + + // Footer padding state + var footerPaddingTop by remember { mutableFloatStateOf(ReadBookConfig.footerPaddingTop.toFloat()) } + var footerPaddingBottom by remember { mutableFloatStateOf(ReadBookConfig.footerPaddingBottom.toFloat()) } + var footerPaddingLeft by remember { mutableFloatStateOf(ReadBookConfig.footerPaddingLeft.toFloat()) } + var footerPaddingRight by remember { mutableFloatStateOf(ReadBookConfig.footerPaddingRight.toFloat()) } + val tipNames = remember { ReadBookConfig.tipNames } val tipValues = remember { ReadBookConfig.tipValues } @@ -153,7 +208,7 @@ internal fun HeaderFooterPage( scope.launch { pagerState.animateScrollToPage( page = index, - animationSpec = tween(durationMillis = 400, easing = FastOutSlowInEasing) + animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing) ) } }, @@ -181,7 +236,7 @@ internal fun HeaderFooterPage( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp) - .verticalScroll(rememberScrollState()), + .verticalScroll(headerScrollState), ) { TinySwitchSettingItem( title = stringResource(R.string.showLine), @@ -252,6 +307,48 @@ internal fun HeaderFooterPage( showColorPicker = true }, ) + Spacer(Modifier.height(8.dp)) + TinyClickableSettingItem( + title = stringResource(R.string.padding), + description = "上: ${headerPaddingTop.toInt()} 下: ${headerPaddingBottom.toInt()} 左: ${headerPaddingLeft.toInt()} 右: ${headerPaddingRight.toInt()}", + trailingContent = { + Icon( + imageVector = if (expandHeaderPadding) Icons.Default.ExpandMore else Icons.Default.ChevronRight, + contentDescription = null, + tint = LegadoTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.size(20.dp), + ) + }, + onClick = { expandHeaderPadding = !expandHeaderPadding }, + ) + AnimatedVisibility( + visible = expandHeaderPadding, + enter = expandVertically() + fadeIn(), + exit = shrinkVertically() + fadeOut(), + ) { + Column(modifier = Modifier.fillMaxWidth()) { + PaddingSliders( + top = headerPaddingTop, bottom = headerPaddingBottom, + left = headerPaddingLeft, right = headerPaddingRight, + onTopChange = { + headerPaddingTop = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.HeaderPaddingTop(it.toInt()))) + }, + onBottomChange = { + headerPaddingBottom = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.HeaderPaddingBottom(it.toInt()))) + }, + onLeftChange = { + headerPaddingLeft = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.HeaderPaddingLeft(it.toInt()))) + }, + onRightChange = { + headerPaddingRight = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.HeaderPaddingRight(it.toInt()))) + }, + ) + } + } } } @@ -261,7 +358,7 @@ internal fun HeaderFooterPage( modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp) - .verticalScroll(rememberScrollState()), + .verticalScroll(footerScrollState), ) { TinySwitchSettingItem( title = stringResource(R.string.showLine), @@ -332,6 +429,48 @@ internal fun HeaderFooterPage( showColorPicker = true }, ) + Spacer(Modifier.height(8.dp)) + TinyClickableSettingItem( + title = stringResource(R.string.padding), + description = "上: ${footerPaddingTop.toInt()} 下: ${footerPaddingBottom.toInt()} 左: ${footerPaddingLeft.toInt()} 右: ${footerPaddingRight.toInt()}", + trailingContent = { + Icon( + imageVector = if (expandFooterPadding) Icons.Default.ExpandMore else Icons.Default.ChevronRight, + contentDescription = null, + tint = LegadoTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.size(20.dp), + ) + }, + onClick = { expandFooterPadding = !expandFooterPadding }, + ) + AnimatedVisibility( + visible = expandFooterPadding, + enter = expandVertically() + fadeIn(), + exit = shrinkVertically() + fadeOut(), + ) { + Column(modifier = Modifier.fillMaxWidth()) { + PaddingSliders( + top = footerPaddingTop, bottom = footerPaddingBottom, + left = footerPaddingLeft, right = footerPaddingRight, + onTopChange = { + footerPaddingTop = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.FooterPaddingTop(it.toInt()))) + }, + onBottomChange = { + footerPaddingBottom = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.FooterPaddingBottom(it.toInt()))) + }, + onLeftChange = { + footerPaddingLeft = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.FooterPaddingLeft(it.toInt()))) + }, + onRightChange = { + footerPaddingRight = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.FooterPaddingRight(it.toInt()))) + }, + ) + } + } } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/PaddingConfigSheet.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/PaddingConfigSheet.kt index 27f3040bb..dfb3a18c5 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/PaddingConfigSheet.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/PaddingConfigSheet.kt @@ -3,18 +3,11 @@ package io.legado.app.ui.book.read.sheet import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue -import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -24,8 +17,6 @@ import io.legado.app.ui.book.read.ConfigUpdate import io.legado.app.ui.book.read.ReadBookIntent import io.legado.app.ui.widget.components.modalBottomSheet.AppModalBottomSheet import io.legado.app.ui.widget.components.settingItem.TinySliderSettingItem -import io.legado.app.ui.widget.components.tabRow.CardTabRow -import kotlinx.coroutines.launch @Composable fun PaddingConfigSheet( @@ -58,122 +49,35 @@ fun PaddingConfigContent( var paddingBottom by remember { mutableFloatStateOf(ReadBookConfig.paddingBottom.toFloat()) } var paddingLeft by remember { mutableFloatStateOf(ReadBookConfig.paddingLeft.toFloat()) } var paddingRight by remember { mutableFloatStateOf(ReadBookConfig.paddingRight.toFloat()) } - // Header padding - var headerPaddingTop by remember { mutableFloatStateOf(ReadBookConfig.headerPaddingTop.toFloat()) } - var headerPaddingBottom by remember { mutableFloatStateOf(ReadBookConfig.headerPaddingBottom.toFloat()) } - var headerPaddingLeft by remember { mutableFloatStateOf(ReadBookConfig.headerPaddingLeft.toFloat()) } - var headerPaddingRight by remember { mutableFloatStateOf(ReadBookConfig.headerPaddingRight.toFloat()) } - // Footer padding - var footerPaddingTop by remember { mutableFloatStateOf(ReadBookConfig.footerPaddingTop.toFloat()) } - var footerPaddingBottom by remember { mutableFloatStateOf(ReadBookConfig.footerPaddingBottom.toFloat()) } - var footerPaddingLeft by remember { mutableFloatStateOf(ReadBookConfig.footerPaddingLeft.toFloat()) } - var footerPaddingRight by remember { mutableFloatStateOf(ReadBookConfig.footerPaddingRight.toFloat()) } - - val scope = rememberCoroutineScope() - val tabTitles = listOf( - stringResource(R.string.header), - stringResource(R.string.main_body), - stringResource(R.string.footer), - ) - val pagerState = rememberPagerState(pageCount = { 3 }) - var selectedTab by remember { mutableIntStateOf(0) } - - LaunchedEffect(pagerState) { - snapshotFlow { pagerState.settledPage }.collect { selectedTab = it } - } Column( modifier = modifier.fillMaxWidth(), ) { - CardTabRow( - tabTitles = tabTitles, - selectedTabIndex = selectedTab, - onTabSelected = { index -> - selectedTab = index - scope.launch { pagerState.animateScrollToPage(index) } + PaddingSliders( + top = paddingTop, bottom = paddingBottom, + left = paddingLeft, right = paddingRight, + onTopChange = { + paddingTop = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.PaddingTop(it.toInt()))) + }, + onBottomChange = { + paddingBottom = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.PaddingBottom(it.toInt()))) + }, + onLeftChange = { + paddingLeft = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.PaddingLeft(it.toInt()))) + }, + onRightChange = { + paddingRight = it + onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.PaddingRight(it.toInt()))) }, - modifier = Modifier.padding(bottom = 8.dp), ) - HorizontalPager( - state = pagerState, - modifier = Modifier.fillMaxWidth(), - ) { page -> - when (page) { - 0 -> Column(modifier = Modifier.padding(vertical = 8.dp)) { - PaddingSliders( - top = headerPaddingTop, bottom = headerPaddingBottom, - left = headerPaddingLeft, right = headerPaddingRight, - onTopChange = { - headerPaddingTop = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.HeaderPaddingTop(it.toInt()))) - }, - onBottomChange = { - headerPaddingBottom = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.HeaderPaddingBottom(it.toInt()))) - }, - onLeftChange = { - headerPaddingLeft = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.HeaderPaddingLeft(it.toInt()))) - }, - onRightChange = { - headerPaddingRight = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.HeaderPaddingRight(it.toInt()))) - }, - ) - } - - 1 -> Column(modifier = Modifier.padding(vertical = 8.dp)) { - PaddingSliders( - top = paddingTop, bottom = paddingBottom, - left = paddingLeft, right = paddingRight, - onTopChange = { - paddingTop = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.PaddingTop(it.toInt()))) - }, - onBottomChange = { - paddingBottom = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.PaddingBottom(it.toInt()))) - }, - onLeftChange = { - paddingLeft = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.PaddingLeft(it.toInt()))) - }, - onRightChange = { - paddingRight = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.PaddingRight(it.toInt()))) - }, - ) - } - - 2 -> Column(modifier = Modifier.padding(vertical = 8.dp)) { - PaddingSliders( - top = footerPaddingTop, bottom = footerPaddingBottom, - left = footerPaddingLeft, right = footerPaddingRight, - onTopChange = { - footerPaddingTop = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.FooterPaddingTop(it.toInt()))) - }, - onBottomChange = { - footerPaddingBottom = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.FooterPaddingBottom(it.toInt()))) - }, - onLeftChange = { - footerPaddingLeft = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.FooterPaddingLeft(it.toInt()))) - }, - onRightChange = { - footerPaddingRight = it - onIntent(ReadBookIntent.UpdateConfig(ConfigUpdate.FooterPaddingRight(it.toInt()))) - }, - ) - } - } - } } } @Composable -private fun PaddingSliders( +internal fun PaddingSliders( top: Float, bottom: Float, left: Float, right: Float, onTopChange: (Float) -> Unit, onBottomChange: (Float) -> Unit, onLeftChange: (Float) -> Unit, onRightChange: (Float) -> Unit, diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadStyleSheet.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadStyleSheet.kt index c606d3ebd..6d874e8e0 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadStyleSheet.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/ReadStyleSheet.kt @@ -38,6 +38,7 @@ import kotlinx.coroutines.launch @Composable fun ReadStyleContent( onOpenPaddingConfig: () -> Unit, + onOpenHeaderFooterConfig: () -> Unit, onOpenMoreConfig: () -> Unit, onOpenBgTextConfig: (Int) -> Unit, onOpenTextTitle: () -> Unit, @@ -51,7 +52,7 @@ fun ReadStyleContent( styleConfig: ReadBookStyleConfig = ReadBookStyleConfig(), ) { val scope = rememberCoroutineScope() - val pagerState = rememberPagerState(pageCount = { 3 }) + val pagerState = rememberPagerState(pageCount = { 2 }) var currentPage by remember { mutableIntStateOf(0) } val pageHeights = remember { mutableStateMapOf() } @@ -105,10 +106,6 @@ fun ReadStyleContent( bottomBarButtons = bottomBarButtons, onIntent = onIntent, ) - - 2 -> HeaderFooterPage( - onIntent = onIntent, - ) } } } @@ -123,15 +120,17 @@ fun ReadStyleContent( tabTitles = tabTitles, selectedTabIndex = currentPage, onTabSelected = { index -> - if (index < 3) { - scope.launch { - pagerState.animateScrollToPage( - page = index, - animationSpec = tween(durationMillis = 400, easing = FastOutSlowInEasing) - ) + when (index) { + 0, 1 -> { + scope.launch { + pagerState.animateScrollToPage( + page = index, + animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing) + ) + } } - } else { - onOpenMoreConfig() + 2 -> onOpenHeaderFooterConfig() + 3 -> onOpenMoreConfig() } }, modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = 8.dp), diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/SystemMenuPage.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/SystemMenuPage.kt index 572759a08..34677d596 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/SystemMenuPage.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/SystemMenuPage.kt @@ -128,7 +128,7 @@ internal fun SystemMenuPage( scope.launch { pagerState.animateScrollToPage( page = index, - animationSpec = tween(durationMillis = 400, easing = FastOutSlowInEasing) + animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing) ) } }, From 87f01900c31a94ef215604ca487ddcf746aaa186 Mon Sep 17 00:00:00 2001 From: fansangg Date: Sun, 14 Jun 2026 04:02:10 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix:=E5=8A=A8=E7=94=BB=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/book/read/sheet/HeaderFooterPage.kt | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt index 1ed7d6097..2ab8c1dc5 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt @@ -2,6 +2,7 @@ package io.legado.app.ui.book.read.sheet import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.FastOutSlowInEasing +import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.tween import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn @@ -22,13 +23,12 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ChevronRight import androidx.compose.material.icons.filled.ExpandMore import androidx.compose.material.icons.filled.TextFields -import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableIntStateOf @@ -43,21 +43,19 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringArrayResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.core.net.toUri import androidx.lifecycle.compose.collectAsStateWithLifecycle import io.legado.app.R -import io.legado.app.ui.theme.LegadoTheme import io.legado.app.data.repository.ReadPreferences import io.legado.app.data.repository.ReadSettingsRepository import io.legado.app.help.config.ReadBookConfig import io.legado.app.ui.book.read.ConfigUpdate import io.legado.app.ui.book.read.ReadBookIntent +import io.legado.app.ui.theme.LegadoTheme import io.legado.app.ui.widget.components.FontSelectSheet import io.legado.app.ui.widget.components.dialog.ColorPickerSheet import io.legado.app.ui.widget.components.settingItem.TinyClickableSettingItem @@ -70,6 +68,7 @@ import io.legado.app.utils.getCompatColor import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.koin.compose.koinInject +import kotlin.time.Duration.Companion.milliseconds // Color picker IDs private const val COLOR_HEADER = 7 @@ -127,19 +126,23 @@ internal fun HeaderFooterPage( LaunchedEffect(expandHeaderPadding) { if (expandHeaderPadding) { - snapshotFlow { headerScrollState.maxValue } - .collect { maxVal -> - headerScrollState.scrollTo(maxVal) - } + //等动画结束后再滚动到底部,否则maxValue值不是最新 + delay(300.milliseconds) + headerScrollState.animateScrollTo( + headerScrollState.maxValue, + animationSpec = tween(durationMillis = 200, easing = LinearEasing) + ) } } LaunchedEffect(expandFooterPadding) { if (expandFooterPadding) { - snapshotFlow { footerScrollState.maxValue } - .collect { maxVal -> - footerScrollState.scrollTo(maxVal) - } + //等动画结束后再滚动到底部,否则maxValue值不是最新 + delay(300.milliseconds) + footerScrollState.animateScrollTo( + footerScrollState.maxValue, + animationSpec = tween(durationMillis = 200, easing = LinearEasing) + ) } } @@ -319,7 +322,9 @@ internal fun HeaderFooterPage( modifier = Modifier.size(20.dp), ) }, - onClick = { expandHeaderPadding = !expandHeaderPadding }, + onClick = { + expandHeaderPadding = !expandHeaderPadding + }, ) AnimatedVisibility( visible = expandHeaderPadding, @@ -441,7 +446,9 @@ internal fun HeaderFooterPage( modifier = Modifier.size(20.dp), ) }, - onClick = { expandFooterPadding = !expandFooterPadding }, + onClick = { + expandFooterPadding = !expandFooterPadding + }, ) AnimatedVisibility( visible = expandFooterPadding, From c3ba892fa397d8cd57548187a7862cd2cc9fa3d3 Mon Sep 17 00:00:00 2001 From: fansangg Date: Sun, 14 Jun 2026 04:50:59 +0800 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E9=A1=B5=E7=9C=89?= =?UTF-8?q?=E9=A1=B5=E8=84=9A=E9=97=B4=E8=B7=9D=E5=B1=95=E5=BC=80=E6=BB=9A?= =?UTF-8?q?=E5=8A=A8=E5=B9=B6=E6=8F=90=E5=8F=96=E7=A1=AC=E7=BC=96=E7=A0=81?= =?UTF-8?q?=E8=BE=B9=E8=B7=9D=E5=AD=97=E7=AC=A6=E4=B8=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/book/read/sheet/HeaderFooterPage.kt | 37 +++++++++---------- app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values-zh-rHK/strings.xml | 1 + app/src/main/res/values-zh-rTW/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 5 files changed, 22 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt b/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt index 2ab8c1dc5..0919bcdba 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt @@ -2,7 +2,6 @@ package io.legado.app.ui.book.read.sheet import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.FastOutSlowInEasing -import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.tween import androidx.compose.animation.expandVertically import androidx.compose.animation.fadeIn @@ -65,10 +64,8 @@ import io.legado.app.ui.widget.components.settingItem.TinySliderSettingItem import io.legado.app.ui.widget.components.settingItem.TinySwitchSettingItem import io.legado.app.ui.widget.components.tabRow.CardTabRow import io.legado.app.utils.getCompatColor -import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.koin.compose.koinInject -import kotlin.time.Duration.Companion.milliseconds // Color picker IDs private const val COLOR_HEADER = 7 @@ -124,25 +121,15 @@ internal fun HeaderFooterPage( val headerScrollState = rememberScrollState() val footerScrollState = rememberScrollState() - LaunchedEffect(expandHeaderPadding) { + LaunchedEffect(expandHeaderPadding, headerScrollState.maxValue) { if (expandHeaderPadding) { - //等动画结束后再滚动到底部,否则maxValue值不是最新 - delay(300.milliseconds) - headerScrollState.animateScrollTo( - headerScrollState.maxValue, - animationSpec = tween(durationMillis = 200, easing = LinearEasing) - ) + headerScrollState.scrollTo(headerScrollState.maxValue) } } - LaunchedEffect(expandFooterPadding) { + LaunchedEffect(expandFooterPadding, footerScrollState.maxValue) { if (expandFooterPadding) { - //等动画结束后再滚动到底部,否则maxValue值不是最新 - delay(300.milliseconds) - footerScrollState.animateScrollTo( - footerScrollState.maxValue, - animationSpec = tween(durationMillis = 200, easing = LinearEasing) - ) + footerScrollState.scrollTo(footerScrollState.maxValue) } } @@ -313,7 +300,13 @@ internal fun HeaderFooterPage( Spacer(Modifier.height(8.dp)) TinyClickableSettingItem( title = stringResource(R.string.padding), - description = "上: ${headerPaddingTop.toInt()} 下: ${headerPaddingBottom.toInt()} 左: ${headerPaddingLeft.toInt()} 右: ${headerPaddingRight.toInt()}", + description = stringResource( + R.string.padding_format, + headerPaddingTop.toInt(), + headerPaddingBottom.toInt(), + headerPaddingLeft.toInt(), + headerPaddingRight.toInt(), + ), trailingContent = { Icon( imageVector = if (expandHeaderPadding) Icons.Default.ExpandMore else Icons.Default.ChevronRight, @@ -437,7 +430,13 @@ internal fun HeaderFooterPage( Spacer(Modifier.height(8.dp)) TinyClickableSettingItem( title = stringResource(R.string.padding), - description = "上: ${footerPaddingTop.toInt()} 下: ${footerPaddingBottom.toInt()} 左: ${footerPaddingLeft.toInt()} 右: ${footerPaddingRight.toInt()}", + description = stringResource( + R.string.padding_format, + footerPaddingTop.toInt(), + footerPaddingBottom.toInt(), + footerPaddingLeft.toInt(), + footerPaddingRight.toInt(), + ), trailingContent = { Icon( imageVector = if (expandFooterPadding) Icons.Default.ExpandMore else Icons.Default.ChevronRight, diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 2364dff3a..073d0ae09 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -352,6 +352,7 @@ 下边距 左边距 右边距 + 上: %1$d 下: %2$d 左: %3$d 右: %4$d 校验书源 校验所选 %1$s 进度 %2$d/%3$d diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index a362ecf2a..663a98f39 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -299,6 +299,7 @@ 下邊距 左邊距 右邊距 + 上: %1$d 下: %2$d 左: %3$d 右: %4$d 校驗書源 校驗所選 %1$s 進度 %2$d/%3$d diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index dacc5b224..13fa803b2 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -301,6 +301,7 @@ 下邊距 左邊距 右邊距 + 上: %1$d 下: %2$d 左: %3$d 右: %4$d 校驗書源 校驗所選 %1$s 進度 %2$d/%3$d diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eb0394a28..bd7822aa7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -373,6 +373,7 @@ Bottom Left Right + Top: %1$d Bottom: %2$d Left: %3$d Right: %4$d Check book sources Check the selected source %1$s Progress %2$d/%3$d