iOS like over scroll effect on Android

后端 未结 3 2050
南旧
南旧 2021-01-31 19:58

I want to implement the iOS-like bounce overscroll effect in my app.

I came across this link which suggests creating a custom ScrollView. But the problem is

3条回答
  •  迷失自我
    2021-01-31 20:06

    Thanks to Xaver Kapeller, I have written my solution with overriding fling and little additions, using kotlin and androidx

    Add coordinator dependency

    implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
    

    Create a new class that extends CoordinatorLayout.Behavior

    import android.content.Context
    import android.util.AttributeSet
    import android.view.View
    import android.view.ViewGroup
    import android.view.animation.AccelerateDecelerateInterpolator
    import androidx.coordinatorlayout.widget.CoordinatorLayout
    import androidx.core.view.ViewCompat
    
    class OverScrollBehavior(context: Context, attributeSet: AttributeSet)
    : CoordinatorLayout.Behavior() {
    
    companion object {
        private const val OVER_SCROLL_AREA = 4
    }
    
    private var overScrollY = 0
    
    override fun onStartNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: View,
        directTargetChild: View,
        target: View,
        axes: Int,
        type: Int
    ): Boolean {
        overScrollY = 0
        return true
    }
    
    override fun onNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: View,
        target: View,
        dxConsumed: Int,
        dyConsumed: Int,
        dxUnconsumed: Int,
        dyUnconsumed: Int,
        type: Int,
        consumed: IntArray
    ) {
        if (dyUnconsumed == 0) {
            return
        }
    
        overScrollY -= (dyUnconsumed/OVER_SCROLL_AREA)
        val group = target as ViewGroup
        val count = group.childCount
        for (i in 0 until count) {
            val view = group.getChildAt(i)
            view.translationY = overScrollY.toFloat()
        }
    }
    
    override fun onStopNestedScroll(
        coordinatorLayout: CoordinatorLayout,
        child: View,
        target: View,
        type: Int
    ) {
        // Smooth animate to 0 when the user stops scrolling
        moveToDefPosition(target)
    }
    
    override fun onNestedPreFling(
        coordinatorLayout: CoordinatorLayout,
        child: View,
        target: View,
        velocityX: Float,
        velocityY: Float
    ): Boolean {
        // Scroll view by inertia when current position equals to 0
        if (overScrollY == 0) {
            return false
        }
        // Smooth animate to 0 when user fling view
        moveToDefPosition(target)
        return true
    }
    
    private fun moveToDefPosition(target: View) {
        val group = target as ViewGroup
        val count = group.childCount
        for (i in 0 until count) {
            val view = group.getChildAt(i)
            ViewCompat.animate(view)
                .translationY(0f)
                .setInterpolator(AccelerateDecelerateInterpolator())
                .start()
        }
    }
    
    }
    

    Create XML file with CoordinatorLayout and NestedScrollView

    
    
        
            
        
    
    

    And don't forget to add

    app:layout_behavior=".OverScrollBehavior" // Or your file name
    

    field to your NestedScrollView XML markup

提交回复
热议问题