Есть ли способ заставить работать синхронно два горизонтальных пейджера библиотеки концертмейстеров?

Я пытаюсь добиться, если есть два горизонтальных пейджера, а затем, проведя пальцем по верхнему левому, нижний горизонтальный пейджер должен провести вправо и наоборот, попытался использовать метод pagerState scrollBy, но не получил желаемого результата

1 ответ

В первую очередь нужно определить, какой пейджер прокручивается, а какой должен следовать за ним. Это можно сделать с isScrollInProgress, я использую его внутри derivedStateOfчтобы избежать ненужных повторных композиций.

Тогда я бегу. Я передаю пару состояний пейджера в нужном порядке или нуль, как key, так LaunchedEffectбудет перезапущен при остановке/начале прокрутки. С использованием snapshotFlow, можно отслеживать изменения результата блока, вычисления которого зависят от изменения состояния.

PagerStateимеет информацию о положении прокрутки в свойствах currentPageа также . scrollToPageберет только 0..1значения смещения страницы, но currentPageOffsetможет быть меньше нуля при прокрутке назад.

Предполагать currentPage = 2а также currentPageOffset = -0.1. В этом случае я получу 1.9в pagePart, и мне нужно разделить его, чтобы получить 1а также 0.9. Для этого я использую divideAndRemainder: он вернет список формы listOf(1.0, 0.9).

      Column {
    val count = 10
    val firstPagerState = rememberPagerState()
    val secondPagerState = rememberPagerState()

    val scrollingFollowingPair by remember {
        derivedStateOf {
            if (firstPagerState.isScrollInProgress) {
                firstPagerState to secondPagerState
            } else if (secondPagerState.isScrollInProgress) {
                secondPagerState to firstPagerState
            } else null
        }
    }
    LaunchedEffect(scrollingFollowingPair) {
        val (scrollingState, followingState) = scrollingFollowingPair ?: return@LaunchedEffect
        snapshotFlow { scrollingState.currentPage + scrollingState.currentPageOffset }
            .collect { pagePart ->
                val divideAndRemainder = BigDecimal.valueOf(pagePart.toDouble())
                    .divideAndRemainder(BigDecimal.ONE)

                followingState.scrollToPage(
                    divideAndRemainder[0].toInt(),
                    divideAndRemainder[1].toFloat(),
                )
            }
    }

    HorizontalPager(
        count = count,
        state = firstPagerState,
        modifier = Modifier.weight(1f)
    ) {
        Text(it.toString())
    }
    HorizontalPager(
        count = count,
        state = secondPagerState,
        modifier = Modifier.weight(1f)
    ) {
        Text(it.toString())
    }
}

Результат:

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