2

I'm using ScalingLazyColumn with a very long Text inside as follows:

@Preview(device = Devices.WEAR_OS_SMALL_ROUND, showSystemUi = true)
@Composable
fun Test(modifier: Modifier = Modifier) {
    val scalingLazyState = remember { ScalingLazyListState() }
    val focusRequester = remember { FocusRequester() }

    Scaffold(
        modifier = modifier,
        positionIndicator = { PositionIndicator(scalingLazyListState = scalingLazyState) }
    ) {
        ScalingLazyColumn(
            modifier = Modifier.scrollableColumn(focusRequester, scalingLazyState),
            state = scalingLazyState,
        ) {
            item {
                Text(
                    longText,
                    Modifier
                        .padding(top = 20.dp, start = 16.dp, end = 16.dp, bottom = 48.dp),
                    textAlign = TextAlign.Center,
                )
            }
        }

    }
}

val longText =
    "Take the plunge\n" +
            "\n" +
            "commit oneself to a course of action about which one is nervous.\n" +
            "\n" +
            "\"she wondered whether to enter for the race, but decided to take the plunge\"\n" +
            "\"They're finally taking the plunge and getting married.\"\n" +
            "\n" +
            "\n" +
            "plunge:\n" +
            "jump or dive quickly and energetically.\n" +
            "\"our daughters whooped as they plunged into the sea\"\n"

But for some reason when I launch the app the focus goes to the bottom of the text, instead of the beginning, which looks like a bug. I've tried playing with different parameters of ScalingLazyColumn (anchorType, autoCentering, scalingParams) to no avail.

demo

Any idea how to fix it and make the ScalingLazyColumn focus on the beginning of the first element when I launch the app?

konnovdev
  • 823
  • 8
  • 16

4 Answers4

6

Switching off autoCentering is an option, but I would try and avoid it in most cases as it will will make handling getting the padding right on different devices sizes more difficult and often results in being able to over scroll the list items either at the beginning or the end.

I am not sure exactly what you want to achieve when you say that you want the focus to be on the start of the first item but the following should give you what you need.

  1. Set the state initial item to 0
  2. Set the anchor type to ScalingLazyListAnchorType.ItemStart
  3. Remove top padding from your item
  4. Apply an offset to the state initialItem initialCenterItemScrollOffset to shift the start of you item up a little.
  5. Optionally adjust the autoCentering to make sure that the limit of the scrolling matches the initial position selected in the state
@Preview(device = Devices.WEAR_OS_SMALL_ROUND, showSystemUi = true)
@Composable
fun SingleItemSLCWithLongText(modifier: Modifier = Modifier) {
    val scalingLazyState = remember { ScalingLazyListState(initialCenterItemIndex = 0, initialCenterItemScrollOffset = 80) }
    val focusRequester = remember { FocusRequester() }

    Scaffold(
        modifier = modifier.background(Color.Black),
        positionIndicator = { PositionIndicator(scalingLazyListState = scalingLazyState) }
    ) {
        ScalingLazyColumn(
            modifier = Modifier.scrollableColumn(focusRequester, scalingLazyState),
            autoCentering = AutoCenteringParams(itemIndex = 0, itemOffset = 80),
            state = scalingLazyState,
            anchorType = ScalingLazyListAnchorType.ItemStart
        ) {
            item {
                Text(
                    longText,
                    Modifier
                        .padding(start = 16.dp, end = 16.dp, bottom = 48.dp),
                    textAlign = TextAlign.Center,
                )
            }
        }

    }
}

Here is a screenshot of how the screen initially looks

Initial screen

2

This test activity let's you play with all the params to see starting position

https://github.com/google/horologist/blob/a1241ff25b7008f7c1337f4425b98d14ce30d96d/sample/src/main/java/com/google/android/horologist/scratch/ScratchActivity.kt

enter image description here

Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69
1

After a few hours of frustration I finally found a solution. If you read the documentation for ScalingLazyColumn it says:

"If the developer wants custom control over position and spacing they can switch off autoCentering and provide contentPadding."

So all you need to do is to just add autoCentering = null in ScalingLazyColumn.

This is a working code where the focus will be in the beginning of the Text:

    val scalingLazyState = remember { ScalingLazyListState() }
    val focusRequester = remember { FocusRequester() }

    Scaffold(
        modifier = modifier,
        positionIndicator = { PositionIndicator(scalingLazyListState = scalingLazyState) }
    ) {
        ScalingLazyColumn(
            modifier = Modifier.scrollableColumn(focusRequester, scalingLazyState),
            state = scalingLazyState,
            autoCentering = null,
        ) {
            item {
                Text(
                    longText,
                    Modifier
                        .padding(top = 20.dp, start = 16.dp, end = 16.dp, bottom = 48.dp),
                    textAlign = TextAlign.Center,
                )
            }
        }
    }
konnovdev
  • 823
  • 8
  • 16
  • The contentPadding it talks about is a parameter on ScalingLazyColumn. ``` public fun ScalingLazyColumn( modifier: Modifier = Modifier, state: ScalingLazyListState = rememberScalingLazyListState(), contentPadding: PaddingValues = PaddingValues(horizontal = 10.dp), ``` – Yuri Schimke Nov 10 '22 at 09:28
0

ScalingLazyListState defaults to the center of the second item (index 1). You can tell it to instead start in the first item and even jn the ScalingLazyColumn parameters use the start of items.


            val scalingLazyState = remember { ScalingLazyListState(initialCenterItemIndex = 0) }
            val focusRequester = remember { FocusRequester() }

            Scaffold(
                modifier = Modifier,
                positionIndicator = { PositionIndicator(scalingLazyListState = scalingLazyState) }
            ) {
                ScalingLazyColumn(
                    modifier = Modifier.scrollableColumn(focusRequester, scalingLazyState),
                    state = scalingLazyState,
                    anchorType = ScalingLazyListAnchorType.ItemStart
                ) {
                    item {
                        Text(
                            longText,
                            Modifier
                                .padding(top = 20.dp, start = 16.dp, end = 16.dp, bottom = 48.dp),
                            textAlign = TextAlign.Center,
                        )
                    }
                }

            }
Yuri Schimke
  • 12,435
  • 3
  • 35
  • 69