and*_*321 1 scroll kotlin android-jetpack-compose android-jetpack-compose-lazy-column
如何检测用户何时在 LazyColumn 中向上或向下滚动?我试图在用户向下滚动时隐藏屏幕上的元素,并在用户开始向上滚动时再次显示它。
lazyListState.firstVisibleItemIndex这可以通过将和与它们之前的值进行比较来完成lazyListState.firstVisibleItemScrollOffset。
您可以像 LazyListState 一样封装此逻辑
class DirectionalLazyListState(
private val lazyListState: LazyListState
) {
private var positionY = lazyListState.firstVisibleItemScrollOffset
private var visibleItem = lazyListState.firstVisibleItemIndex
val scrollDirection by derivedStateOf {
if (lazyListState.isScrollInProgress.not()) {
ScrollDirection.None
} else {
val firstVisibleItemIndex = lazyListState.firstVisibleItemIndex
val firstVisibleItemScrollOffset =
lazyListState.firstVisibleItemScrollOffset
// We are scrolling while first visible item hasn't changed yet
if (firstVisibleItemIndex == visibleItem) {
val direction = if (firstVisibleItemScrollOffset > positionY) {
ScrollDirection.Down
} else {
ScrollDirection.Up
}
positionY = firstVisibleItemScrollOffset
direction
} else {
val direction = if (firstVisibleItemIndex > visibleItem) {
ScrollDirection.Down
} else {
ScrollDirection.Up
}
positionY = firstVisibleItemScrollOffset
visibleItem = firstVisibleItemIndex
direction
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过记住调用构造函数
@Composable
fun rememberDirectionalLazyListState(
lazyListState: LazyListState,
): DirectionalLazyListState {
return remember {
DirectionalLazyListState(lazyListState)
}
}
Run Code Online (Sandbox Code Playgroud)
并使用它
val lazyListState = rememberLazyListState()
val directionalLazyListState = rememberDirectionalLazyListState(
lazyListState
)
Run Code Online (Sandbox Code Playgroud)
枚举类
enum class ScrollDirection {
Up, Down, None
}
Run Code Online (Sandbox Code Playgroud)
完整演示
@Preview
@Composable
private fun ScrollDirectionSample() {
val lazyListState = rememberLazyListState()
val directionalLazyListState = rememberDirectionalLazyListState(
lazyListState
)
val text by remember {
derivedStateOf {
"isScrollInProgress: ${lazyListState.isScrollInProgress}\n" +
"firstVisibleItemIndex: ${lazyListState.firstVisibleItemIndex}\n" +
"firstVisibleItemScrollOffset: ${lazyListState.firstVisibleItemScrollOffset}"
}
}
val color = when (directionalLazyListState.scrollDirection) {
ScrollDirection.Up -> Color.Green
ScrollDirection.Down -> Color.Blue
else -> Color.Black
}
Column {
Text(text, fontSize = 16.sp)
Text(
"Direction: ${directionalLazyListState.scrollDirection}",
fontSize = 24.sp,
color = color,
fontWeight = FontWeight.Bold
)
LazyColumn(
state = lazyListState,
modifier = Modifier.fillMaxSize()
) {
items(50) {
Text(
text = "Row $it",
fontSize = 22.sp,
color = Color.White,
modifier = Modifier
.fillMaxWidth()
.background(Color.Red)
.padding(8.dp)
)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码无法确定手指按下时是移动还是向下还是空闲,因为按下时无论指针是否未移动isScrollInProgress都会返回true 。如果用户在按下指针时不移动指针或isScrollInProgress为 true,则可以添加超时设置为“无”。
@Stable
class DirectionalLazyListState(
private val lazyListState: LazyListState,
private val coroutineScope: CoroutineScope
) {
private var positionY = lazyListState.firstVisibleItemScrollOffset
private var visibleItem = lazyListState.firstVisibleItemIndex
private var currentTime = System.currentTimeMillis()
var scrollDirection by mutableStateOf(ScrollDirection.None)
init {
coroutineScope.launch {
while (isActive) {
delay(120)
if (System.currentTimeMillis() - currentTime > 120) {
scrollDirection = ScrollDirection.None
}
}
}
snapshotFlow {
val scrollInt = if (lazyListState.isScrollInProgress) 20000 else 10000
val visibleItemInt = lazyListState.firstVisibleItemIndex * 10
scrollInt + visibleItemInt + lazyListState.firstVisibleItemScrollOffset
}
.onEach {
if (lazyListState.isScrollInProgress.not()) {
scrollDirection = ScrollDirection.None
} else {
currentTime = System.currentTimeMillis()
val firstVisibleItemIndex = lazyListState.firstVisibleItemIndex
val firstVisibleItemScrollOffset =
lazyListState.firstVisibleItemScrollOffset
// We are scrolling while first visible item hasn't changed yet
if (firstVisibleItemIndex == visibleItem) {
val direction = if (firstVisibleItemScrollOffset > positionY) {
ScrollDirection.Down
} else {
ScrollDirection.Up
}
positionY = firstVisibleItemScrollOffset
scrollDirection = direction
} else {
val direction = if (firstVisibleItemIndex > visibleItem) {
ScrollDirection.Down
} else {
ScrollDirection.Up
}
positionY = firstVisibleItemScrollOffset
visibleItem = firstVisibleItemIndex
scrollDirection = direction
}
}
}
.launchIn(coroutineScope)
}
// val scrollDirection by derivedStateOf {
// if (lazyListState.isScrollInProgress.not()) {
// ScrollDirection.None
// } else {
// val firstVisibleItemIndex = lazyListState.firstVisibleItemIndex
// val firstVisibleItemScrollOffset =
// lazyListState.firstVisibleItemScrollOffset
//
// // We are scrolling while first visible item hasn't changed yet
// if (firstVisibleItemIndex == visibleItem) {
// val direction = if (firstVisibleItemScrollOffset > positionY) {
// ScrollDirection.Down
// } else {
// ScrollDirection.Up
// }
// positionY = firstVisibleItemScrollOffset
//
// direction
// } else {
//
// val direction = if (firstVisibleItemIndex > visibleItem) {
// ScrollDirection.Down
// } else {
// ScrollDirection.Up
// }
// positionY = firstVisibleItemScrollOffset
// visibleItem = firstVisibleItemIndex
// direction
// }
// }
// }
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1343 次 |
| 最近记录: |