Ошибка в поведении ScalingLazyColumn по умолчанию (Jetpack Compose Wear OS)

Я использую ScalingLazyColumn с очень длинным текстом внутри следующим образом:

@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"

Но по какой-то причине, когда я запускаю приложение, фокус переходит на конец текста, а не на начало, что выглядит как ошибка. Я пытался играть с различными параметрами ScalingLazyColumn (anchorType, autoCentering, scalingParams) безрезультатно.

Любая идея, как это исправить и заставить ScalingLazyColumn фокусироваться на начале первого элемента при запуске приложения?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
129
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

ScalingLazyListState по умолчанию находится в центре второго элемента (индекс 1). Вместо этого вы можете указать ему начинать с первого элемента, и даже в параметрах ScalingLazyColumn использовать начало элементов.


            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,
                        )
                    }
                }

            }

Пробовал так, не получилось

konnovdev 10.11.2022 08:28

ах, я вижу, вы прикрепили фрагмент кода. Да, это работает, но при этом он слишком сильно прыгает вверх, где у вас первая верхняя половина экрана пуста, а нижняя половина экрана начинается с первого элемента.

konnovdev 10.11.2022 14:51

Версия Джона Никола исправляет это, добавляя смещения.

konnovdev 10.11.2022 14:57

После нескольких часов разочарования я наконец нашел решение. Если вы читаете документацию для ScalingLazyColumn, там написано:

«Если разработчику нужен собственный контроль над положением и расстоянием, он можно отключить автоцентрирование и предоставить contentPadding».

Так что все, что вам нужно сделать, это просто добавить autoCentering = null в ScalingLazyColumn.

Это рабочий код, в котором фокус будет находиться в начале текста:

    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,
                )
            }
        }
    }

ContentPadding, о котором он говорит, является параметром ScalingLazyColumn. ``` public fun ScalingLazyColumn( модификатор: Модификатор = Модификатор, состояние: ScalingLazyListState = запомнитьScalingLazyListState(), contentPadding: PaddingValues ​​= PaddingValues(horizontal = 10.dp), ```

Yuri Schimke 10.11.2022 10:28

Это тестовое задание позволит вам поиграть со всеми параметрами, чтобы увидеть начальную позицию.

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

Ответ принят как подходящий

Отключение автоцентрирования — это вариант, но я бы старался избегать его в большинстве случаев, так как это усложнит обработку правильного заполнения на устройствах разных размеров и часто приводит к возможности прокручивать элементы списка либо в начале, либо конец.

Я не совсем уверен, чего вы хотите достичь, когда говорите, что хотите, чтобы фокус был на начале первого элемента, но следующее должно дать вам то, что вам нужно.

  1. Установите начальный элемент состояния на 0
  2. Установите тип якоря на ScalingLazyListAnchorType.ItemStart
  3. Удалите верхний отступ из вашего элемента
  4. Примените смещение к состоянию initialItem initialCenterItemScrollOffset, чтобы немного сдвинуть начало вашего элемента.
  5. При необходимости отрегулируйте автоцентрирование, чтобы убедиться, что предел прокрутки соответствует начальной позиции, выбранной в состоянии.
@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,
                )
            }
        }

    }
}

Вот скриншот того, как изначально выглядит экран

Начальный экран

Другие вопросы по теме