如何检测 LazyColumn 中的滚动行为?
我正在尝试检测三种情况:
1.- 用户垂直(向下)滚动并通知隐藏按钮
2.- 用户停止滚动并通知隐藏按钮
3.- 用户垂直(向上)滚动并通知显示按钮
4.- 用户位于列表底部,没有更多项目并通知显示按钮。
我尝试过的是:
第一种方法是使用nestedScrollConnection
,如下所示
val isVisible = remember { MutableTransitionState(false) }
.apply { targetState = true }
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(
available: Offset,
source: NestedScrollSource
): Offset {
return Offset.Zero
}
override fun onPostScroll(
consumed: Offset,
available: Offset,
source: NestedScrollSource
): Offset {
isVisible.targetState = false
return super.onPostScroll(consumed, available, source)
}
}
}
LazyColumn(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, top = 16.dp)
.nestedScroll(nestedScrollConnection),
verticalArrangement = Arrangement.spacedBy(16.dp),
)
。 0 正在上升,否则正在下降,但其他我不知道如何获得它们。
我遵循的另一种方法是:
val scrollState = rememberLazyListState()
LazyColumn(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, top = 16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
state = scrollState,
但我不知道如何获取它是否是最后一项,我可以获取滚动是否正在进行。
注意
Skizo 的答案是有效的,但是这有点奇怪,因为如果你慢慢向上滚动,Y 有时不是我想要的,然后再次隐藏它,有没有办法留下一些滚动来开始对此做出反应?例如,滚动 X 像素即可开始显示/隐藏。
我想要的是隐藏/显示一个浮动操作按钮,具体取决于滚动(场景是上面的场景)
我找到了这种方式,但它使用了偏移量,我想为 制作动画FloatActionButton
而不是像淡入/淡出那样从底部出现,我使用的是 动画可见性 我得到了这个工作淡入/淡出,但现在,我如何调整 github 上的代码以使用动画可见性
?并且当用户结束滚动时添加此内容,从现在开始在代码中只是在滚动时
I'm trying to detect three scenarios :
1.- User scroll vertically (down) and notify to hide a button
2.- User stop scrolls and notify to hide button
3.- User scroll vertically (up) and notify to show the button
4.- User is in the bottom of the list and there are no more items and notify to show the button.
What I've tried is :
First approach is to use nestedScrollConnection
as follows
val isVisible = remember { MutableTransitionState(false) }
.apply { targetState = true }
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(
available: Offset,
source: NestedScrollSource
): Offset {
return Offset.Zero
}
override fun onPostScroll(
consumed: Offset,
available: Offset,
source: NestedScrollSource
): Offset {
isVisible.targetState = false
return super.onPostScroll(consumed, available, source)
}
}
}
LazyColumn(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, top = 16.dp)
.nestedScroll(nestedScrollConnection),
verticalArrangement = Arrangement.spacedBy(16.dp),
)
What I've tried is when y > 0 is going up, else is going down, but the others I don't know how to get them.
Another approach I followed is :
val scrollState = rememberLazyListState()
LazyColumn(
modifier = Modifier
.padding(start = 16.dp, end = 16.dp, top = 16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
state = scrollState,
But I don't know how to get if it's last item or not, I can get if the scroll is in progress.
Note
Answer from Skizo works but with this it's a bit weird because if you scroll up slowly the Y sometimes is not what I want and then hide it again, is there any way to leave some scroll to start reacting to this? For instance, scroll X pixels to start showing / hiding.
What I want is to hide/show is a Float Action Button depending on the scroll (the scenarios are the ones from above)
I've found this way, but it is using the offset and I'd like to animate the FloatActionButton
instead of appearing from the bottom like a fade in/fade out I was using the Animation Visibility and I got this working with fade in/fade out but now, how can I adapt the code from github to use Animation Visibility
? And also add this when the user ends scrolling that from now in the code is just while scrolling
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
以下是实现这些目标的方法:
1.) 检测滚动方向(垂直向上或垂直向下)
现在,只需创建一个 listState 变量并将其与此可组合项一起使用即可检索滚动方向。
然后,正如您所说,您希望在用户停止滚动时收到通知,因此您只需创建一个名为
restingScrollPosition
的变量,我将其命名为rsp简称。现在您已经熟悉了所需的帮助器方法,所需要做的就是设计一种机制来根据当前滚动位置的值触发事件,如果特定数量的值相同,则触发相关代码时间(卷轴的定义是“静止”)。
所以,
我不认为我会在这里解释最后一段代码的工作原理,请自己分析以获得更好的理解,这并不难。
啊,是的,要实现最后一个目标,您只需对 API 使用一点虚张声势,特别是像
lazyListState.layoutInfo
这样的方法。它包含您需要的有关屏幕上当前可见项目的所有信息,因此您还可以使用它来实现您的微妙需求,即您希望在触发代码块之前允许滚动一定量。只需查看对象中的可用信息,您就应该能够启动它。更新:
根据昨天添加的评论中提供的信息,这应该是实现,
您在层次结构中的某个位置有一个 FAB,并且您希望根据
动画它的可见性>isScrollingUp
,它绑定到层次结构中其他地方定义的Lazy Scroller,在这种情况下,你可以看一下状态提升,这是声明式编程的一般最佳实践。
只需将
isScrollingUp()
输出提升到声明 FAB 的位置即可,或者如果您需要根据您的用例进行特定说明,请分享完整的代码。我需要整个家族能够帮助你解决这个问题。Here's how you'd go about achieving these,
1.) Detect The Scrolling Direction (Vertically Up, or Vertically Down)
Now, just create a listState variable and use it with this Composable to retrieve the scrolling dierection.
Then, as you say, you'd like to get notified if the user stops scrolling, so for that you can just create a variable known as
restingScrollPosition
, I'll name itrsp
for short. Now that you are familiar with the required helper methods, all that is required is devising a mechanism to trigger an event based on the value of the current scroll position that triggers the code in concern if the value has been the same for a particular amount of time (the definition of the scroll being "at rest").So, here it is
I don't think I would be explaining the workings of the last code here, please analyze it yourself to gain a better understanding, it's not difficult.
Ah yes to achieve the last objective, you can just use a little swashbuckling with the APIs, specifically methods like
lazyListState.layoutInfo
. It has all the info you'll require about the items currently visible on-screen, and so you can also use it to implement your subtle need where you wish to allow for a certain amount to be scrolled before triggering the codeblock. Just have a look at the availannle info in the object and you should be able to start it up.UPDATE:
Based on the info provided in the comments added below as of yesterday, this should be the implementation,
You have a FAB somewhere in your heirarchy, and you wish to animate it's visibility based on the
isScrollingUp
, which is bound to the Lazy Scroller defined somewhere else in the heirarchy,In that case, you can take a look at state-hoisting, which is a general best practice for declarative programming.
Just hoist the
isScrollingUp()
output up to the point where your FAB is declared, or please share the complete code if you need specific instructions based on your use-case. I would require the entire heirarchy to be able to help you out with this.几天前我也遇到了同样的问题,我按照你说的做了一些混合。
要显示或隐藏,然后使用
Y
向上或向下滚动就足够了。并检测没有更多可以使用的物品
I've faced same problem some days ago and I did a mix of what you say.
To show or hide then scrolling up or down with the
Y
is enough.And to detect there's no more items you can use
对于 1 和 3,如果您想在显示/隐藏某些内容之前指定特定的滚动距离,您可以创建一个具有自己状态的
NestedScrollConnection
。这是一个可能会给您一些想法的实现示例。当达到
downThreshold
时,CustomScrollConnection.isScrollingDown
将返回true
,当达到upThreshold 时,它将更改为
。false
已达到您可以在将实例传递给
nestedScroll
修饰符之前创建一个这样的实例。需要额外的代码才能将其与
rememberSaveable
一起使用。对于 2,如果您使用的是
LazyListState
,您可以查看!lazyListState.isScrollInProgress
是否有帮助。对于 4,您可以尝试使用
!lazyListState.canScrollForward
。或者,在NestedScrollConnection
的实现中,如果您重写onPostScroll
,则可以检查consumed.y == 0f &&可用。 0f
;这可能意味着您已触底。For 1 and 3, if you want to specify a specific scroll distance before showing/hiding something, you can create a
NestedScrollConnection
with its own state.Here is an example of an implementation that may give you some ideas.
CustomScrollConnection.isScrollingDown
would returntrue
whendownThreshold
is reached, and it would change tofalse
whenupThreshold
is reached.And you can create an instance like this before passing it to the
nestedScroll
modifier.Additional code would be needed to use it with
rememberSaveable
.For 2, if you are using
LazyListState
, you can see if!lazyListState.isScrollInProgress
helps.For 4, you can try using
!lazyListState.canScrollForward
. Or, in an implementation ofNestedScrollConnection
, if you overrideonPostScroll
, you can check ifconsumed.y == 0f && available.y < 0f
; this could mean you reached the bottom.