捕捉指数lazyrow

发布于 2025-01-21 18:44:40 字数 835 浏览 0 评论 0原文

我在Lazyrow的帮助下制作日历。我现在有一个问题,我希望该行在一定的滚动量后捕捉到索引,以便在索引之间不可能粘在索引中。有办法做到吗?

    LazyRow(state = calendarViewModel.listState, modifier = Modifier.fillMaxWidth()) {
        calendarYears.forEach {
            items(it.months.count()) { index ->
                calendarViewModel.onEvent(CalendarEvent.ClickedMenuItem(index))
                CalendarRowItem(
                    modifier = Modifier.fillParentMaxWidth(),
                    calendarSize = it.months[index].amountOfDays,
                    initWeekday = it.months[index].startDayOfMonth.ordinal,
                    textColor = MaterialTheme.colors.secondaryVariant,
                    clickedColor = MaterialTheme.colors.primary,
                    textStyle = MaterialTheme.typography.body1
                )
            }
        }
    }

I am making a calendar with the help of a lazyRow. I now have the problem that I want the row to snap to the index after a certain scroll amount so it shouldn't be possible to be stuck in between indexes. Is there a way to do that?

    LazyRow(state = calendarViewModel.listState, modifier = Modifier.fillMaxWidth()) {
        calendarYears.forEach {
            items(it.months.count()) { index ->
                calendarViewModel.onEvent(CalendarEvent.ClickedMenuItem(index))
                CalendarRowItem(
                    modifier = Modifier.fillParentMaxWidth(),
                    calendarSize = it.months[index].amountOfDays,
                    initWeekday = it.months[index].startDayOfMonth.ordinal,
                    textColor = MaterialTheme.colors.secondaryVariant,
                    clickedColor = MaterialTheme.colors.primary,
                    textStyle = MaterialTheme.typography.body1
                )
            }
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

心如狂蝶 2025-01-28 18:44:40

首先要组合 1.3.0 您可以使用 将项目捕捉到给定位置:

val state = rememberLazyListState()

LazyRow(
    modifier = Modifier.fillMaxSize(),
    verticalAlignment = Alignment.CenterVertically,
    state = state,
    flingBehavior = rememberSnapFlingBehavior(lazyListState = state)
) {
  //item content
}

Starting with compose 1.3.0 you can use the FlingBehavior that performs snapping of items to a given position:

val state = rememberLazyListState()

LazyRow(
    modifier = Modifier.fillMaxSize(),
    verticalAlignment = Alignment.CenterVertically,
    state = state,
    flingBehavior = rememberSnapFlingBehavior(lazyListState = state)
) {
  //item content
}

enter image description here

生寂 2025-01-28 18:44:40

您可以从 canceranist Libraral 提供提供提供的提供的提供的提供的提供的提供的提供者这种爆炸行为在框外,并在内部使用lazyrow

可以使用 snapper库创建的另一个选项。 /users/474997/chris-banes“>@chris-banes

build.gradle.gradle中添加依赖关系。

dependencies {
    implementation "dev.chrisbanes.snapper:snapper:<version>"
}

并在您的lazyrow中使用它。

val lazyListState = rememberLazyListState()

LazyRow(
    state = lazyListState,
    flingBehavior = rememberSnapperFlingBehavior(lazyListState),
) {
    // content
}

结果:

You can use the HorizontalPager from accompanist library which provides this fling behavior out-of-the-box and it uses LazyRow internally.

Another option could be use the Snapper library created by @chris-banes

Add the dependency in your build.gradle.

dependencies {
    implementation "dev.chrisbanes.snapper:snapper:<version>"
}

and use it in your LazyRow.

val lazyListState = rememberLazyListState()

LazyRow(
    state = lazyListState,
    flingBehavior = rememberSnapperFlingBehavior(lazyListState),
) {
    // content
}

Result:

enter image description here

指尖上的星空 2025-01-28 18:44:40

在Gabriele的答案之上构建,以基于第一个可见项目(侧扣至开始)来捕捉,我们需要执行以下操作:

val scrollState = rememberLazyListState()
val positionInLayout: Density.(Float, Float) -> Float = { _, _ ->
    // This value tells where to snap on the x axis within the viewport
    // Setting it to 0 results in snapping of the first visible item to the left side (or right side if RTL)
    0f
}
val snappingLayout = remember(scrollState) { SnapLayoutInfoProvider(scrollState, positionInLayout) }
val flingBehavior = rememberSnapFlingBehavior(snappingLayout)
LazyRow(
    modifier = modifier,
    state = scrollState,
    contentPadding = PaddingValues(horizontal = 1.5f.u()),
    flingBehavior = flingBehavior,
    content = {}
)

Building on top of Gabriele's answer, for snapping based on first visible item (side snapping to the start) we need to do the following:

val scrollState = rememberLazyListState()
val positionInLayout: Density.(Float, Float) -> Float = { _, _ ->
    // This value tells where to snap on the x axis within the viewport
    // Setting it to 0 results in snapping of the first visible item to the left side (or right side if RTL)
    0f
}
val snappingLayout = remember(scrollState) { SnapLayoutInfoProvider(scrollState, positionInLayout) }
val flingBehavior = rememberSnapFlingBehavior(snappingLayout)
LazyRow(
    modifier = modifier,
    state = scrollState,
    contentPadding = PaddingValues(horizontal = 1.5f.u()),
    flingBehavior = flingBehavior,
    content = {}
)
如果没结果 2025-01-28 18:44:40
val centerItemIndex by remember {
    derivedStateOf {
        val layoutInfo = listState.layoutInfo
        val visibleItems = layoutInfo.visibleItemsInfo
        val viewportCenter = (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2

        visibleItems.minByOrNull { abs((it.offset + it.size / 2) - viewportCenter) }?.index ?: 0
    }
}
val centerItemIndex by remember {
    derivedStateOf {
        val layoutInfo = listState.layoutInfo
        val visibleItems = layoutInfo.visibleItemsInfo
        val viewportCenter = (layoutInfo.viewportStartOffset + layoutInfo.viewportEndOffset) / 2

        visibleItems.minByOrNull { abs((it.offset + it.size / 2) - viewportCenter) }?.index ?: 0
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文