diff options
4 files changed, 45 insertions, 47 deletions
diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/DrawablePainter.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/DrawablePainter.kt index ae325f8862eb..e3e1220633ae 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/DrawablePainter.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/DrawablePainter.kt @@ -20,6 +20,7 @@ import android.graphics.drawable.Animatable import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable +import android.os.Build import android.os.Handler import android.os.Looper import android.view.View @@ -117,13 +118,17 @@ class DrawablePainter( return true } - override fun applyLayoutDirection(layoutDirection: LayoutDirection): Boolean = - drawable.setLayoutDirection( - when (layoutDirection) { - LayoutDirection.Ltr -> View.LAYOUT_DIRECTION_LTR - LayoutDirection.Rtl -> View.LAYOUT_DIRECTION_RTL - } - ) + override fun applyLayoutDirection(layoutDirection: LayoutDirection): Boolean { + if (Build.VERSION.SDK_INT >= 23) { + return drawable.setLayoutDirection( + when (layoutDirection) { + LayoutDirection.Ltr -> View.LAYOUT_DIRECTION_LTR + LayoutDirection.Rtl -> View.LAYOUT_DIRECTION_RTL + } + ) + } + return false + } override val intrinsicSize: Size get() = drawableIntrinsicSize diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/Pager.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/Pager.kt index 4df7794e8759..392089ae7989 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/Pager.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/Pager.kt @@ -19,8 +19,6 @@ package com.android.settingslib.spa.framework.compose import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.calculateEndPadding -import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyRow @@ -36,7 +34,6 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.NestedScrollSource import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.dp @@ -123,7 +120,7 @@ fun VerticalPager( contentPadding: PaddingValues = PaddingValues(0.dp), horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, key: ((page: Int) -> Any)? = null, - content: @Composable() (PagerScope.(page: Int) -> Unit), + content: @Composable PagerScope.(page: Int) -> Unit, ) { Pager( count = count, @@ -175,24 +172,8 @@ internal fun Pager( .collect { state.updateCurrentPageBasedOnLazyListState() } } val density = LocalDensity.current - val layoutDirection = LocalLayoutDirection.current - LaunchedEffect(density, contentPadding, isVertical, layoutDirection, reverseLayout, state) { - with(density) { - // this should be exposed on LazyListLayoutInfo instead. b/200920410 - state.afterContentPadding = if (isVertical) { - if (!reverseLayout) { - contentPadding.calculateBottomPadding() - } else { - contentPadding.calculateTopPadding() - } - } else { - if (!reverseLayout) { - contentPadding.calculateEndPadding(layoutDirection) - } else { - contentPadding.calculateStartPadding(layoutDirection) - } - }.roundToPx() - } + LaunchedEffect(density, state, itemSpacing) { + with(density) { state.itemSpacing = itemSpacing.roundToPx() } } val pagerScope = remember(state) { PagerScopeImpl(state) } @@ -203,6 +184,7 @@ internal fun Pager( ConsumeFlingNestedScrollConnection( consumeHorizontal = !isVertical, consumeVertical = isVertical, + pagerState = state, ) } @@ -268,6 +250,7 @@ internal fun Pager( private class ConsumeFlingNestedScrollConnection( private val consumeHorizontal: Boolean, private val consumeVertical: Boolean, + private val pagerState: PagerState, ) : NestedScrollConnection { override fun onPostScroll( consumed: Offset, @@ -281,9 +264,15 @@ private class ConsumeFlingNestedScrollConnection( } override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity { - // We can consume all post fling velocity on the main-axis - // so that it doesn't propagate up to the Pager - return available.consume(consumeHorizontal, consumeVertical) + return if (pagerState.currentPageOffset != 0f) { + // The Pager is already scrolling. This means that a nested scroll child was + // scrolled to end, and the Pager can use this fling + Velocity.Zero + } else { + // A nested scroll child is still scrolling. We can consume all post fling + // velocity on the main-axis so that it doesn't propagate up to the Pager + available.consume(consumeHorizontal, consumeVertical) + } } } diff --git a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/PagerState.kt b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/PagerState.kt index 21ba11739af0..480335dacd36 100644 --- a/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/PagerState.kt +++ b/packages/SettingsLib/Spa/spa/src/com/android/settingslib/spa/framework/compose/PagerState.kt @@ -85,12 +85,14 @@ class PagerState( return layoutInfo.visibleItemsInfo.maxByOrNull { val start = maxOf(it.offset, 0) val end = minOf( - it.offset + it.size, layoutInfo.viewportEndOffset - afterContentPadding) + it.offset + it.size, + layoutInfo.viewportEndOffset - layoutInfo.afterContentPadding + ) end - start } } - internal var afterContentPadding = 0 + internal var itemSpacing by mutableStateOf(0) private val currentPageLayoutInfo: LazyListItemInfo? get() = lazyListState.layoutInfo.visibleItemsInfo.lastOrNull { @@ -135,9 +137,7 @@ class PagerState( */ val currentPageOffset: Float by derivedStateOf { currentPageLayoutInfo?.let { - // We coerce since itemSpacing can make the offset > 1f. - // We don't want to count spacing in the offset so cap it to 1f - (-it.offset / it.size.toFloat()).coerceIn(-1f, 1f) + (-it.offset / (it.size + itemSpacing).toFloat()).coerceIn(-0.5f, 0.5f) } ?: 0f } @@ -187,28 +187,26 @@ class PagerState( // offset from the size lazyListState.animateScrollToItem( index = page, - scrollOffset = (target.size * pageOffset).roundToInt() + scrollOffset = ((target.size + itemSpacing) * pageOffset).roundToInt() ) } else if (layoutInfo.visibleItemsInfo.isNotEmpty()) { // If we don't, we use the current page size as a guide - val currentSize = layoutInfo.visibleItemsInfo.first().size + val currentSize = layoutInfo.visibleItemsInfo.first().size + itemSpacing lazyListState.animateScrollToItem( index = page, scrollOffset = (currentSize * pageOffset).roundToInt() ) // The target should be visible now - target = lazyListState.layoutInfo.visibleItemsInfo.firstOrNull { - it.index == page - } + target = layoutInfo.visibleItemsInfo.firstOrNull { it.index == page } - if (target != null && target.size != currentSize) { + if (target != null && target.size + itemSpacing != currentSize) { // If the size we used for calculating the offset differs from the actual // target page size, we need to scroll again. This doesn't look great, // but there's not much else we can do. lazyListState.animateScrollToItem( index = page, - scrollOffset = (target.size * pageOffset).roundToInt() + scrollOffset = ((target.size + itemSpacing) * pageOffset).roundToInt() ) } } @@ -248,7 +246,7 @@ class PagerState( if (pageOffset.absoluteValue > 0.0001f) { currentPageLayoutInfo?.let { scroll { - scrollBy(it.size * pageOffset) + scrollBy((it.size + itemSpacing) * pageOffset) } } } @@ -295,7 +293,7 @@ class PagerState( } private fun requireCurrentPageOffset(value: Float, name: String) { - require(value in -1f..1f) { "$name must be >= 0 and <= 1" } + require(value in -1f..1f) { "$name must be >= -1 and <= 1" } } companion object { diff --git a/packages/SettingsLib/Spa/tests/build.gradle b/packages/SettingsLib/Spa/tests/build.gradle index c4a17d8c8920..45f9b23e11d6 100644 --- a/packages/SettingsLib/Spa/tests/build.gradle +++ b/packages/SettingsLib/Spa/tests/build.gradle @@ -76,7 +76,13 @@ task coverageReport(type: JacocoReport, dependsOn: "connectedDebugAndroidTest") sourceDirectories.from = files("../spa/src") classDirectories.from = fileTree( dir: "../spa/build/tmp/kotlin-classes/debug", - excludes: ["com/android/settingslib/spa/debug/**"], + excludes: [ + "com/android/settingslib/spa/debug/**", + + // Excludes files forked from Accompanist. + "com/android/settingslib/spa/framework/compose/DrawablePainter*", + "com/android/settingslib/spa/framework/compose/Pager*", + ], ) executionData.from = fileTree(dir: "$buildDir/outputs/code_coverage/debugAndroidTest/connected") } |