Jetpack Compose - 使用 HorizontalPager 使指示器在 TabRow 中滚动

问题描述 投票:0回答:1

我正在尝试实现一件简单的事情:我有一个 ScrollableTabRow 和一个 HorizontalPager ,我想让 ScrollableTabRow 的指示器在我向左或向右拖动 HorizontalPager 时移动。

现在,只有当我更改页面时它才会移动。

它可以使用 XML 开箱即用,但现在我觉得我必须这样做,但我不知道做什么。

代码:

      ScrollableTabRow(selectedTabIndex = selectedTabIndex.value,
            indicator = { positions ->
                TabRowDefaults.SecondaryIndicator(
                    Modifier.tabIndicatorOffset(positions[pagerState.currentPage])
                )
            },
            modifier = Modifier.fillMaxWidth(),
            containerColor = getTopBarColor()) {
            data.forEachIndexed { index, _ ->
                Tab(
                    text = { Text(tabTitle, maxLines = 1) },
                    selected = selectedTabIndex.value == index,
                    onClick = {
                        scope.launch {
                            pagerState.animateScrollToPage(index)
                        }
                    }
                )
            }
        }
        HorizontalPager(state = pagerState, modifier = Modifier
            .fillMaxWidth()
            .weight(1f)) { page ->
            // Show the page
        }
    ....
android android-jetpack-compose android-jetpack android-scrollable-tabs horizontal-pager
1个回答
0
投票

试试这个

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TabIndicatorScope.SynchronizedIndicator(
    selectedTabIndex: Int,
    pagerOffset: Float,
    modifier: Modifier = Modifier,
    width: Dp = 24.dp,
    height: Dp = 3.dp,
    color: Color = Color.Unspecified,
    shape: Shape = RectangleShape
) {
    Spacer(
        modifier.tabIndicatorLayout { measurable: Measurable,
                                  constraints: Constraints,
                                  tabPositions: List<TabPosition> ->
                val floatingIndex = selectedTabIndex + pagerOffset

                val startTab =
                    tabPositions[floatingIndex
                        .toInt()
                        .coerceIn(0, tabPositions.lastIndex)]
                val endTab =
                    tabPositions[(floatingIndex.toInt() + 1).coerceIn(0, tabPositions.lastIndex)]

                val startCenter = (startTab.left + startTab.right) / 2
                val endCenter = (endTab.left + endTab.right) / 2
                val startIndicatorPosition = startCenter - startTab.contentWidth / 2
                val endIndicatorPosition = endCenter - endTab.contentWidth / 2
                val startIndicatorEndPosition = startCenter + startTab.contentWidth / 2
                val endIndicatorEndPosition = endCenter + endTab.contentWidth / 2

                val progress = floatingIndex - floatingIndex.toInt()

                val indicatorStart =
                    startIndicatorPosition + (endIndicatorPosition - startIndicatorPosition) * progress
                val indicatorEnd =
                    startIndicatorEndPosition + (endIndicatorEndPosition - startIndicatorEndPosition) * progress

                val placeable = measurable.measure(
                    constraints.copy(
                        maxWidth = (indicatorEnd - indicatorStart).roundToPx(),
                        minWidth = (indicatorEnd - indicatorStart).roundToPx()
                    )
                )

                layout(constraints.maxWidth, placeable.height) {
                    placeable.place(indicatorStart.roundToPx(), 0)
                }
            }
            .requiredHeight(height)
            .requiredWidth(width)
            .background(color = color, shape = shape)
    )
}

然后在你的代码中

val pager = rememberPagerState(initialPage = 0) { 4 }

PrimaryTabRow(
   selectedTabIndex = pager.currentPage,
   indicator = {
     SynchronizedIndicator(
        selectedTabIndex = pager.currentPage,
        pagerOffset = pager.currentPageOffsetFraction,
        width = Dp.Unspecified,
        height = 5.dp,
        color = Color.White,
        shape = RoundedCornerShape(topStart = 3.dp, topEnd = 3.dp)
     )
   }
) {
//Your tabs
}
//HorizontalPager

有关指标的更多信息位于此处

© www.soinside.com 2019 - 2024. All rights reserved.