2

Okay so I've got a really interesting questions here. Let's talk snapping. Now that snapping is a 1st class api (RIP Snapper lib) available for compose devs using LazyColumn, a fundamental question has arose... how do I initialize the LazyColumn so that it comes on screen beautifully and perfectly snapped to a defined index/item element in the column rather than visually resting halfway between two elements ? Why no snap? https://developer.android.com/reference/kotlin/androidx/compose/foundation/gestures/snapping/SnapFlingBehavior As you can see here, its very easy and useful to add the snap fling behavior to your LazyColumns - especially if you have long lists in your app. It makes it so anytime you scroll or fling the column, it will snap perfectly onto the final item nearest the center of the LazyColumn Widger The problem is, there is no snapToIndex method provided.... and animateToScrollIndex does not seem Snap friendly as it results in the triggered scroll animation resting to a final location between two elements. Nothing I have tried leads to snapping to an item index programatically. Any ideas ?? There has got to be some possible way to solve this fundamental issue. If there's a way to do this, it could greatly increase the utility of SnapFlingBehavior in LazyColumn and LazyRow world (imho some of the most vital performance related widgets in the framework).

Has anyone found a solution to programmatically controlling the index you are currently snapped to ?

/** Basic usage **/

    val listState = rememberLazyListState()
    
    val flingBehavior = rememberSnapFlingBehavior()
    
    LazyColumn(state = listState, flingBehavior = flingBehavior) 


/** Exampe of things that don't result in snapping to an index **/

    listState by rememberLazyListState(firstVisibleItemIndex: 5)
     listState.animateScrollTo(index: 10)
A.Sanchez.SD
  • 1,950
  • 2
  • 18
  • 23

1 Answers1

1

came to find out that calling

listState.scroll{
    with(flingBehavior) {
      performFling(initialVelocity)
    }

}

From a launched effect and passing in the state and fling behavior you used to configure the LazyColumn will result in the column coming on screen already snapped to an item. So long as you provide a non 0 value for first visible item index when creating your lazy list state.

A.Sanchez.SD
  • 1,950
  • 2
  • 18
  • 23
  • I don't understand how to use this. Did you figure out away to to snap to an index using flingBehavior or only by flinging by a velocity and hopping it maps to the desired index? – cincy_anddeveloper Mar 22 '23 at 14:34
  • @cincy_anddeveloper Without this code, if you provide an initial index when instantiating listState with fling beavior, you might notice that the list might not be "snapped" to an item, it might be ever so close or noticeably out of wack, but by adding this code to a launched effect and providing an initial velocity value (seemed like any low, non zero number works) it will ensure that the List is actually SNAPPED to the index. These apis are a pain- sorry if this is vague. – A.Sanchez.SD Mar 22 '23 at 14:47
  • So, before calling that code above, I should call listState.scrollToItem(itemIndex)? – cincy_anddeveloper Mar 22 '23 at 14:51
  • I'm not using a launched effect but calling scrollToItem(...), then your code above doesn't work when called from a list item click listener. The item scrolls to to be the first visible item aligned along the left edge of the LazyColumn. – cincy_anddeveloper Mar 22 '23 at 15:12
  • Possible the behavior changed in later versions of compose. Haven't tested again since this experiment. – A.Sanchez.SD Mar 30 '23 at 16:41