Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix bottom padding for responsive() SLC #1826

Merged
merged 20 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -165,44 +165,58 @@ public object ScalingLazyColumnDefaults {
val configuration = LocalConfiguration.current
val screenWidthDp = configuration.screenWidthDp.toFloat()
val screenHeightDp = configuration.screenHeightDp.toFloat()
val padding = screenWidthDp * horizontalPaddingPercent
val topPaddingDp: Dp = if (firstItemIsFullWidth && configuration.isScreenRound) {
calculateVerticalOffsetForChip(screenWidthDp, horizontalPaddingPercent)
} else {
32.dp
}

val sizeRatio = ((screenWidthDp - 192) / (233 - 192).toFloat()).coerceIn(0f, 1.5f)
val presetRatio = 0f
return remember {
val padding = screenWidthDp * horizontalPaddingPercent
val topPaddingDp: Dp = if (firstItemIsFullWidth && configuration.isScreenRound) {
calculateVerticalOffsetForChip(screenWidthDp, horizontalPaddingPercent)
} else {
32.dp
}
val bottomPaddingDp: Dp = if (configuration.isScreenRound) {
calculateVerticalOffsetForChip(screenWidthDp, horizontalPaddingPercent)
} else {
0.dp
}
val contentPadding = PaddingValues(
start = padding.dp,
end = padding.dp,
top = topPaddingDp,
bottom = bottomPaddingDp
)

val sizeRatio = ((screenWidthDp - 192) / (233 - 192).toFloat()).coerceIn(0f, 1.5f)
val presetRatio = 0f

val minElementHeight = lerp(0.2f, 0.157f, sizeRatio)
val maxElementHeight = lerp(0.6f, 0.216f, sizeRatio).coerceAtLeast(minElementHeight)
val minTransitionArea = lerp(0.35f, lerp(0.35f, 0.393f, presetRatio), sizeRatio)
val maxTransitionArea = lerp(0.55f, lerp(0.55f, 0.593f, presetRatio), sizeRatio)
val minElementHeight = lerp(0.2f, 0.157f, sizeRatio)
val maxElementHeight = lerp(0.6f, 0.216f, sizeRatio).coerceAtLeast(minElementHeight)
val minTransitionArea = lerp(0.35f, lerp(0.35f, 0.393f, presetRatio), sizeRatio)
val maxTransitionArea = lerp(0.55f, lerp(0.55f, 0.593f, presetRatio), sizeRatio)

val scalingParams = ScalingLazyColumnDefaults.scalingParams(
minElementHeight = minElementHeight,
maxElementHeight = maxElementHeight,
minTransitionArea = minTransitionArea,
maxTransitionArea = maxTransitionArea,
)
val scalingParams = ScalingLazyColumnDefaults.scalingParams(
minElementHeight = minElementHeight,
maxElementHeight = maxElementHeight,
minTransitionArea = minTransitionArea,
maxTransitionArea = maxTransitionArea,
)

return remember {
val screenHeightPx =
with(density) { screenHeightDp.dp.roundToPx() }
val topPaddingPx = with(density) { topPaddingDp.roundToPx() }
val topScreenOffsetPx = screenHeightPx / 2 - topPaddingPx

val initialScrollPosition = ScalingLazyColumnState.ScrollPosition(
index = 0,
offsetPx = topScreenOffsetPx,
)
ScalingLazyColumnState(
initialScrollPosition = ScalingLazyColumnState.ScrollPosition(
index = 0,
offsetPx = topScreenOffsetPx,
),
initialScrollPosition = initialScrollPosition,
autoCentering = null,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that fix replaces some issue with AutoCentering behavior?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AutoCentering API is this

public class AutoCenteringParams(
    // @IntRange(from = 0)
    internal val itemIndex: Int = 1,
    internal val itemOffset: Int = 0,
)

You can ensure that the top is correctly working. However it doesn't ensure that the bottom can be completely scrolled into view.

So better to disable it, and do it manually with enough content padding at the bottom to allow the last item to be unobscured.

anchorType = ScalingLazyListAnchorType.ItemStart,
rotaryMode = RotaryMode.Scroll,
verticalArrangement = verticalArrangement,
horizontalAlignment = Alignment.CenterHorizontally,
contentPadding = PaddingValues(horizontal = padding.dp),
contentPadding = contentPadding,
scalingParams = scalingParams,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,127 @@

package com.google.android.horologist.screensizes

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.wear.compose.material.AppCard
import androidx.wear.compose.material.Text
import com.google.android.horologist.composables.SectionedList
import com.google.android.horologist.compose.layout.ScalingLazyColumnDefaults
import com.google.android.horologist.compose.layout.ScalingLazyColumnState
import com.google.android.horologist.compose.material.Title
import com.google.android.horologist.compose.tools.Device
import com.google.android.horologist.sample.R
import com.google.android.horologist.sample.Screen
import org.junit.Test

class ScalingLazyColumnDefaultsTest(device: Device) :
ScreenSizeTest(device = device, showTimeText = false) {

@Composable
override fun Content() {
Standard()
@Composable
override fun Content() {
Standard()
}

@Test
fun responsive() {
runTest { Responsive() }
}

@Test
fun belowTimeText() {
runTest { BelowTimeText() }
}

@Test
fun standard_end() {
runTest {
val columnState = ScalingLazyColumnDefaults.scalingLazyColumnDefaults().create()

SampleMenu(columnState = columnState)

LaunchedEffect(Unit) {
columnState.state.scrollToItem(100, 0)
}
}
}

@Test
fun responsive_end() {
runTest {
val columnState = ScalingLazyColumnDefaults.responsive().create()

SampleMenu(columnState = columnState)

LaunchedEffect(Unit) {
columnState.state.scrollToItem(100, 0)
}
}
}

@Test
fun responsive() {
runTest { Responsive() }
@Test
fun belowTimeText_end() {
runTest {
val columnState = ScalingLazyColumnDefaults.belowTimeText().create()

SampleMenu(columnState = columnState)

LaunchedEffect(Unit) {
columnState.state.scrollToItem(100, 0)
}
}
}

@Composable
fun SampleMenu(columnState: ScalingLazyColumnState, modifier: Modifier = Modifier) {
SectionedList(
columnState = columnState,
modifier = modifier.fillMaxSize(),
) {
section(
listOf(
Pair(
R.string.sectionedlist_stateless_sections_menu,
Screen.SectionedListStatelessScreen.route,
),
Pair(
R.string.sectionedlist_stateful_sections_menu,
Screen.SectionedListStatefulScreen.route,
),
Pair(
R.string.sectionedlist_expandable_sections_menu,
Screen.SectionedListExpandableScreen.route,
),
),
) {
header {
Title(
stringResource(R.string.sectionedlist_samples_title),
Modifier.padding(vertical = 8.dp),
)
}

@Test
fun belowTimeText() {
runTest { BelowTimeText() }
loaded { item ->
AppCard(
onClick = { },
appName = {
Text("App Name")
},
time = {
Text("12:05")
},
title = {
Text("Title")
}
) {
Text("Content\nContent\nContent")
}
}
}
}
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kpeved without this change, the responsive screens hit this issue.

With the change, they can scroll so the last item is mostly not cutoff.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
yschimke marked this conversation as resolved.
Show resolved Hide resolved
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading