Explorar o código

fix: 修正嵌套分页惯性滑动

HapeLee hai 4 meses
pai
achega
bea1095b0a

+ 7 - 4
app/src/main/java/io/legado/app/ui/book/read/sheet/HeaderFooterPage.kt

@@ -7,6 +7,7 @@ import androidx.compose.animation.expandVertically
 import androidx.compose.animation.fadeIn
 import androidx.compose.animation.fadeOut
 import androidx.compose.animation.shrinkVertically
+import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Spacer
@@ -40,7 +41,6 @@ import androidx.compose.runtime.snapshotFlow
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clipToBounds
-import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.res.stringArrayResource
@@ -59,7 +59,7 @@ import io.legado.app.ui.widget.components.FontFolderState
 import io.legado.app.ui.widget.components.FontSelectSheet
 import io.legado.app.ui.widget.components.SectionTitle
 import io.legado.app.ui.widget.components.dialog.ColorPickerSheet
-import io.legado.app.ui.widget.components.pager.rememberConsumeHorizontalPagerNestedScrollConnection
+import io.legado.app.ui.widget.components.pager.rememberPagerFlingPassThroughConnection
 import io.legado.app.ui.widget.components.settingItem.TinyClickableSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyColorSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyDropdownSettingItem
@@ -91,7 +91,10 @@ internal fun HeaderFooterPage(
     val pagerState = rememberPagerState(pageCount = { 3 })
     var selectedTab by remember { mutableIntStateOf(0) }
     var clickScrollCount by remember { mutableIntStateOf(0) }
-    val childPagerNestedScrollConnection = rememberConsumeHorizontalPagerNestedScrollConnection()
+    val childPagerNestedScrollConnection = rememberPagerFlingPassThroughConnection(
+        state = pagerState,
+        orientation = Orientation.Horizontal,
+    )
 
     val pageHeights = remember { mutableStateMapOf<Int, Int>() }
     val animatedHeight by rememberPagerAnimatedHeight(pagerState, pageHeights)
@@ -221,10 +224,10 @@ internal fun HeaderFooterPage(
         HorizontalPager(
             state = pagerState,
             verticalAlignment = Alignment.Top,
+            pageNestedScrollConnection = childPagerNestedScrollConnection,
             modifier = Modifier
                 .fillMaxWidth()
                 .clipToBounds()
-                .nestedScroll(childPagerNestedScrollConnection)
                 .pagerHeight(animatedHeight),
         ) { page ->
             Box(

+ 7 - 4
app/src/main/java/io/legado/app/ui/book/read/sheet/ReadStyleSheet.kt

@@ -2,6 +2,7 @@ package io.legado.app.ui.book.read.sheet
 
 import androidx.compose.animation.core.FastOutSlowInEasing
 import androidx.compose.animation.core.tween
+import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -21,7 +22,6 @@ import androidx.compose.runtime.snapshotFlow
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clipToBounds
-import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.layout.layout
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.platform.LocalDensity
@@ -33,7 +33,7 @@ import io.legado.app.ui.book.read.ConfigUpdate
 import io.legado.app.ui.book.read.ReadBookButtonConfigItem
 import io.legado.app.ui.book.read.ReadBookIntent
 import io.legado.app.ui.book.read.ReadBookStyleConfig
-import io.legado.app.ui.widget.components.pager.rememberConsumeHorizontalPagerNestedScrollConnection
+import io.legado.app.ui.widget.components.pager.rememberPagerFlingPassThroughConnection
 import io.legado.app.ui.widget.components.tabRow.CardTabRow
 import kotlinx.coroutines.launch
 
@@ -56,7 +56,10 @@ fun ReadStyleContent(
     val scope = rememberCoroutineScope()
     val pagerState = rememberPagerState(pageCount = { 2 })
     var currentPage by remember { mutableIntStateOf(0) }
-    val childPagerNestedScrollConnection = rememberConsumeHorizontalPagerNestedScrollConnection()
+    val childPagerNestedScrollConnection = rememberPagerFlingPassThroughConnection(
+        state = pagerState,
+        orientation = Orientation.Horizontal,
+    )
 
     val pageHeights = remember { mutableStateMapOf<Int, Int>() }
     val animatedHeight by rememberPagerAnimatedHeight(pagerState, pageHeights)
@@ -75,10 +78,10 @@ fun ReadStyleContent(
         HorizontalPager(
             state = pagerState,
             verticalAlignment = Alignment.Top,
+            pageNestedScrollConnection = childPagerNestedScrollConnection,
             modifier = Modifier
                 .weight(1f, fill = false)
                 .clipToBounds()
-                .nestedScroll(childPagerNestedScrollConnection)
                 .pagerHeight(animatedHeight),
         ) { page ->
             Box(

+ 7 - 4
app/src/main/java/io/legado/app/ui/book/read/sheet/SystemMenuPage.kt

@@ -4,6 +4,7 @@ import android.content.Context
 import androidx.compose.animation.AnimatedVisibility
 import androidx.compose.animation.core.FastOutSlowInEasing
 import androidx.compose.animation.core.tween
+import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.fillMaxWidth
@@ -46,7 +47,6 @@ import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clip
 import androidx.compose.ui.draw.clipToBounds
-import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.graphics.vector.ImageVector
 import androidx.compose.ui.layout.onSizeChanged
@@ -69,7 +69,7 @@ import io.legado.app.ui.book.read.ReadBookButtonConfigItem
 import io.legado.app.ui.book.read.ReadBookIntent
 import io.legado.app.ui.book.read.ReadBookSheet
 import io.legado.app.ui.theme.LegadoTheme
-import io.legado.app.ui.widget.components.pager.rememberConsumeHorizontalPagerNestedScrollConnection
+import io.legado.app.ui.widget.components.pager.rememberPagerFlingPassThroughConnection
 import io.legado.app.ui.widget.components.SectionTitle
 import io.legado.app.ui.widget.components.dialog.ColorPickerSheet
 import io.legado.app.ui.widget.components.settingItem.TinyClearColorModeSettingItem
@@ -111,7 +111,10 @@ internal fun SystemMenuPage(
     val pagerState = rememberPagerState(pageCount = { 3 })
     var selectedTab by remember { mutableIntStateOf(0) }
     var clickScrollCount by remember { mutableIntStateOf(0) }
-    val childPagerNestedScrollConnection = rememberConsumeHorizontalPagerNestedScrollConnection()
+    val childPagerNestedScrollConnection = rememberPagerFlingPassThroughConnection(
+        state = pagerState,
+        orientation = Orientation.Horizontal,
+    )
 
     val pageHeights = remember { mutableStateMapOf<Int, Int>() }
     val animatedHeight by rememberPagerAnimatedHeight(pagerState, pageHeights)
@@ -161,9 +164,9 @@ internal fun SystemMenuPage(
         HorizontalPager(
             state = pagerState,
             verticalAlignment = Alignment.Top,
+            pageNestedScrollConnection = childPagerNestedScrollConnection,
             modifier = Modifier
                 .weight(1f, fill = false)
-                .nestedScroll(childPagerNestedScrollConnection)
                 .clipToBounds()
                 .pagerHeight(animatedHeight),
         ) { page ->

+ 7 - 4
app/src/main/java/io/legado/app/ui/book/read/sheet/TextTitleSheet.kt

@@ -2,6 +2,7 @@ package io.legado.app.ui.book.read.sheet
 
 import androidx.compose.animation.core.FastOutSlowInEasing
 import androidx.compose.animation.core.tween
+import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
 import androidx.compose.foundation.layout.Spacer
@@ -35,7 +36,6 @@ import androidx.compose.runtime.snapshotFlow
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.clipToBounds
-import androidx.compose.ui.input.nestedscroll.nestedScroll
 import androidx.compose.ui.layout.onSizeChanged
 import androidx.compose.ui.res.stringArrayResource
 import androidx.compose.ui.res.stringResource
@@ -49,7 +49,7 @@ import io.legado.app.ui.widget.components.AppTextField
 import io.legado.app.ui.widget.components.SectionTitle
 import io.legado.app.ui.widget.components.alert.AppAlertDialog
 import io.legado.app.ui.widget.components.dialog.ColorPickerSheet
-import io.legado.app.ui.widget.components.pager.rememberConsumeHorizontalPagerNestedScrollConnection
+import io.legado.app.ui.widget.components.pager.rememberPagerFlingPassThroughConnection
 import io.legado.app.ui.widget.components.settingItem.TinyClickableSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyColorSettingItem
 import io.legado.app.ui.widget.components.settingItem.TinyDropdownSettingItem
@@ -135,7 +135,10 @@ internal fun ReadStyleTextTitleContent(
 ) {
     val pageHeights = remember { mutableStateMapOf<Int, Int>() }
     val animatedHeight by rememberPagerAnimatedHeight(pagerState, pageHeights)
-    val childPagerNestedScrollConnection = rememberConsumeHorizontalPagerNestedScrollConnection()
+    val childPagerNestedScrollConnection = rememberPagerFlingPassThroughConnection(
+        state = pagerState,
+        orientation = Orientation.Horizontal,
+    )
 
     Column(
         modifier = modifier
@@ -152,10 +155,10 @@ internal fun ReadStyleTextTitleContent(
         HorizontalPager(
             state = pagerState,
             verticalAlignment = Alignment.Top,
+            pageNestedScrollConnection = childPagerNestedScrollConnection,
             modifier = Modifier
                 .fillMaxWidth()
                 .clipToBounds()
-                .nestedScroll(childPagerNestedScrollConnection)
                 .pagerHeight(animatedHeight),
         ) { page ->
             Box(

+ 7 - 3
app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfScreen.kt

@@ -27,6 +27,7 @@ import androidx.compose.animation.scaleOut
 import androidx.compose.animation.shrinkVertically
 import androidx.compose.animation.togetherWith
 import androidx.compose.foundation.ExperimentalFoundationApi
+import androidx.compose.foundation.gestures.Orientation
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
@@ -129,7 +130,7 @@ import io.legado.app.ui.widget.components.list.TopFloatingStickyItem
 import io.legado.app.ui.widget.components.log.AppLogSheet
 import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenu
 import io.legado.app.ui.widget.components.menuItem.RoundDropdownMenuItem
-import io.legado.app.ui.widget.components.pager.rememberConsumeHorizontalPagerNestedScrollConnection
+import io.legado.app.ui.widget.components.pager.rememberPagerFlingPassThroughConnection
 import io.legado.app.ui.widget.components.progressIndicator.AppCircularProgressIndicator
 import io.legado.app.ui.widget.components.tabRow.AppTabRow
 import io.legado.app.ui.widget.components.text.AppText
@@ -232,7 +233,10 @@ fun BookshelfScreen(
         initialPage = uiState.selectedGroupIndex.coerceAtLeast(0),
         pageCount = { uiState.groups.size }
     )
-    val childPagerNestedScrollConnection = rememberConsumeHorizontalPagerNestedScrollConnection()
+    val childPagerNestedScrollConnection = rememberPagerFlingPassThroughConnection(
+        state = pagerState,
+        orientation = Orientation.Horizontal,
+    )
     val latestGroups by rememberUpdatedState(uiState.groups)
     val latestSelectedGroupId by rememberUpdatedState(uiState.selectedGroupId)
 
@@ -835,9 +839,9 @@ fun BookshelfScreen(
                     } else {
                         HorizontalPager(
                             state = pagerState,
+                            pageNestedScrollConnection = childPagerNestedScrollConnection,
                             modifier = Modifier
                                 .fillMaxSize()
-                                .nestedScroll(childPagerNestedScrollConnection)
                                 .then(
                                     with(sharedTransitionScope) {
                                         if (this != null) Modifier.skipToLookaheadSize() else Modifier

+ 54 - 23
app/src/main/java/io/legado/app/ui/widget/components/pager/PagerNestedScroll.kt

@@ -1,5 +1,8 @@
 package io.legado.app.ui.widget.components.pager
 
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.pager.PagerDefaults
+import androidx.compose.foundation.pager.PagerState
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.remember
 import androidx.compose.ui.geometry.Offset
@@ -7,29 +10,57 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
 import androidx.compose.ui.input.nestedscroll.NestedScrollSource
 import androidx.compose.ui.unit.Velocity
 
-@Composable
-fun rememberConsumeHorizontalPagerNestedScrollConnection(): NestedScrollConnection {
-    return remember {
-        object : NestedScrollConnection {
-            override fun onPostScroll(
-                consumed: Offset,
-                available: Offset,
-                source: NestedScrollSource,
-            ): Offset {
-                return if (source == NestedScrollSource.Drag && available.x != 0f) {
-                    Offset(x = available.x, y = 0f)
-                } else {
-                    Offset.Zero
-                }
-            }
-
-            override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
-                return if (available.x != 0f) {
-                    Velocity(x = available.x, y = 0f)
-                } else {
-                    Velocity.Zero
-                }
-            }
+private class PagerFlingPassThroughConnection(
+    private val delegate: NestedScrollConnection,
+    private val orientation: Orientation,
+) : NestedScrollConnection {
+
+    private fun Velocity.reverseOnOrientation(): Velocity {
+        return if (orientation == Orientation.Horizontal) {
+            copy(x = -x, y = 0f)
+        } else {
+            copy(x = 0f, y = -y)
         }
     }
+
+    override fun onPreScroll(
+        available: Offset,
+        source: NestedScrollSource,
+    ): Offset {
+        return delegate.onPreScroll(available, source)
+    }
+
+    override fun onPostScroll(
+        consumed: Offset,
+        available: Offset,
+        source: NestedScrollSource,
+    ): Offset {
+        return delegate.onPostScroll(consumed, available, source)
+    }
+
+    override suspend fun onPreFling(available: Velocity): Velocity {
+        return delegate.onPreFling(available)
+    }
+
+    override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
+        delegate.onPostFling(consumed, available)
+        return consumed.reverseOnOrientation()
+    }
+}
+
+@Composable
+fun rememberPagerFlingPassThroughConnection(
+    state: PagerState,
+    orientation: Orientation,
+): NestedScrollConnection {
+    val defaultConnection = PagerDefaults.pageNestedScrollConnection(
+        state = state,
+        orientation = orientation,
+    )
+    return remember(state, orientation, defaultConnection) {
+        PagerFlingPassThroughConnection(
+            delegate = defaultConnection,
+            orientation = orientation,
+        )
+    }
 }