Halil Ozercan

    Halil Ozercan

    1 year ago
    Implemented this view by using
    swipeable
    modifier. However,
    swipeable
    accepts a predefined map of anchors which are limited unless the developer wants to put thousands of anchor points in there. Instead, I reset the swipe state everytime it gets settled and aggregate the total swipe amount. My question; is there a canonical way of doing this snapping behavior without swipeable?
    The weird swipe reset looks like this
    val swipeableState = rememberSwipeableState(initialValue = 0)
    var daysOffset by remember { mutableStateOf(0) }
    val progress = swipeableState.progress
    
    LaunchedEffect(progress) {
        if (progress.fraction == 1f && <http://progress.to|progress.to> == progress.from) {
            daysOffset -= <http://progress.to|progress.to>
            swipeableState.snapTo(0)
        }
    }
    .swipeable(
        state = swipeableState,
        anchors = (-7..7)
            .map {
                it * (24 * 3600 / secondPerPixel) to it
            }
            .toMap(),
        orientation = Orientation.Horizontal
    )
    Only 7 anchors are enough because view is limited by a week. If there is no swipe reset, scrolling would completely stop in one week range.
    Doris Liu

    Doris Liu

    1 year ago
    For this type of more custom snapping behavior that has outgrown the convenient
    swipeable
    API, you might want to reach for a lower level API. In this case, I'd recommend
    dragable
    and
    Animatable
    . It may not be that much more code than the hack you have right now. 😛 At the end of the drag, you'd need to use that velocity to calculate the natural stopping point, find the closest anchor among any number of anchors that you might have, and
    animateTo
    it. In fact, there's a good example in the animation codelab for this.
    Under gesture animation, there's a section on how to calculate the natural stopping point/targetValue: https://developer.android.com/codelabs/jetpack-compose-animation#7
    You could probably achieve the same using a
    scrollable
    with a custom
    FlingBehavior
    🙂
    Halil Ozercan

    Halil Ozercan

    1 year ago
    Thanks a lot @Doris Liu, I'll try both methods 👍
    @Doris Liu scrollable+fling felt like the better approach here considering the trade-offs. Animatable + Draggable required lower level API operations that felt unnecessary for this kind of use-case. Swipeable hack also rarely caused crashes. That actually happens whenever I use swipeable and want to access
    swipeable.progress
    .
    Doris Liu

    Doris Liu

    1 year ago
    Could you file a bug including a stack trace of the crash? I don't expect crashes here even with the hack. 🙂