Reputation: 197
I want to scroll the lazyColumn
when its child get focused.
I use rememberLazyListState
's scrollToItem
method to scroll the lazyColumn
.
but when a item at top been scrolled out, it can't be focused again.
My sample code:
@Composable
fun ScrollableList(modifier: Modifier = Modifier) {
val scrollState = rememberLazyListState()
val scope = rememberCoroutineScope()
LazyColumn(
state = scrollState,
modifier = Modifier.padding(5.dp),
verticalArrangement = Arrangement.spacedBy(5.dp)
) {
itemsIndexed(items = (0..10).toList()) { index, item ->
FocusableBox(
title = "ScrollBox-$index",
onFocused = { focused ->
scope.launch {
if (focused) {
scrollState.scrollToItem(index)
}
}
})
}
}
}
@Composable
fun FocusableBox(
title: String,
onFocused: (Boolean) -> Unit = {},
requester: FocusRequester = FocusRequester(),
modifier: Modifier = Modifier
) {
var boxColor by remember { mutableStateOf(Color.White) }
var focused by remember { mutableStateOf(false) }
Box(
Modifier
.focusRequester(requester)
.onFocusChanged {
boxColor = if (it.isFocused) Color.Green else Color.Gray
focused = it.isFocused
onFocused(it.isFocused)
}
.focusable()
.background(boxColor)
.zIndex(if (focused) 1f else 0f)
) {
Text(
text = title,
modifier = Modifier.padding(30.dp),
color = Color.White,
style = MaterialTheme.typography.subtitle2
)
}
}
Upvotes: 3
Views: 2873
Reputation: 197
add
val scrollState = rememberLazyListState()
then after child been focused, use scrollState.layoutInfo.visibleItemsInfo
to determine scroll up or scroll down.
@Composable
fun ScrollableList(modifier: Modifier = Modifier) {
val scrollState = rememberLazyListState()
val scope = rememberCoroutineScope()
LazyColumn(
state = scrollState,
modifier = Modifier.padding(5.dp),
verticalArrangement = Arrangement.spacedBy(5.dp)
) {
itemsIndexed(items = (0..10).toList()) { index, item ->
FocusableBox(
title = "ScrollBox-$index",
onFocused = { focused ->
scope.launch {
if (focused) {
val visibleItemsInfo = scrollState.layoutInfo.visibleItemsInfo
val visibleSet = visibleItemsInfo.map { it.index }.toSet()
if (index == visibleItemsInfo.last().index) {
scrollState.scrollToItem(index)
} else if (visibleSet.contains(index) && index != 0) {
scrollState.scrollToItem(index - 1)
}
}
}
})
}
}
}
Upvotes: 2