2

I want to scroll the lazyColumn when its child get focused.

I use rememberLazyListState's scrollToItem method to scroll the lazyColumn.

enter image description here

but when a item at top been scrolled out, it can't be focused again.

enter image description here

enter image description here

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
        )
    }
}
TangSir
  • 147
  • 11
  • Check out this Article, https://medium.com/google-developer-experts/focus-in-jetpack-compose-6584252257fe – Vaibhav Goyal Aug 26 '21 at 04:44
  • 3
    Please whenever you paste sample code, remove the unnecessary stuff like decorations and layout positioning. Provide only necessary stuff to highlight and analyse the problem in concern. It increases your chances of the question being answered. – Richard Onslow Roper Aug 26 '21 at 09:27

1 Answers1

1

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)
                            }
                        }
                    }
                })
        }
    }
}

TangSir
  • 147
  • 11