ViewGroup 滑动练习


package com.wuhongru.workman.myView

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.ViewConfiguration
import android.view.ViewGroup
import android.widget.OverScroller
import androidx.constraintlayout.motion.widget.MotionInterpolator
import androidx.core.view.children
import kotlin.math.abs
import kotlin.math.min

class TwoPager(context: Context, attrs: AttributeSet) : ViewGroup(context, attrs) {
    private val viewConfiguration = ViewConfiguration.get(context)

    //Distance in pixels a touch can wander before we think the user is scrolling a full page
    //在我们认为用户滚动整个页面之前,触摸可能会偏离的距离(以像素为单位)
    private val pagingSlop = viewConfiguration.scaledPagingTouchSlop

    //Minimum velocity to initiate a fling, as measured in pixels per second.
    //启动投掷的最小速度,以每秒像素数为单位。
    private val minVelocity = viewConfiguration.scaledMinimumFlingVelocity

    //启动投掷的最大速度,以每秒像素数为单位。
    private val maxVelocity = viewConfiguration.scaledMaximumFlingVelocity

    private val velocityTracker = VelocityTracker.obtain()

    private var isScrolling = false
    private var downX = 0f
    private var downY = 0f
    private var downScrollX = 0f
    private val overScroller = OverScroller(context)

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        //给所有子view边界
        measureChildren(widthMeasureSpec, heightMeasureSpec)
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var childLeft = 0
        val childTop = 0
        var childRight = width
        val childBottom = height
        for (child in children) {
            child.layout(childLeft, childTop, childRight, childBottom)
            childLeft += width
            childRight += width
        }
    }

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        if(event.actionMasked == MotionEvent.ACTION_DOWN){
            Log.e("wuhongru",scrollX.toString())
            velocityTracker.clear()
        }
        velocityTracker.addMovement(event)
        var result = false
        when(event.actionMasked){
            MotionEvent.ACTION_DOWN->{
                downX = event.x
                downY = event.y
                isScrolling = false
                downScrollX = scrollX.toFloat()
            }
            MotionEvent.ACTION_MOVE->{
                if(!isScrolling){
                    val dx = event.x-downX
                    if (abs(dx)>pagingSlop){
                        isScrolling = true
                        parent.requestDisallowInterceptTouchEvent(true)
                        result = true
                    }
                }
            }
        }
        return result
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if(event.actionMasked == MotionEvent.ACTION_DOWN){
            velocityTracker.clear()
        }
        velocityTracker.addMovement(event)
        when(event.actionMasked){
            MotionEvent.ACTION_DOWN->{
                downX = event.x
                downY = event.y
                downScrollX = scrollX.toFloat()
            }
            MotionEvent.ACTION_MOVE->{
                val dx = (downScrollX-(event.x-downX)).toInt()
                    .coerceAtLeast(0)
                    .coerceAtMost(width)
                scrollTo(dx,0)
            }
            MotionEvent.ACTION_UP->{
                velocityTracker.computeCurrentVelocity(1000,maxVelocity.toFloat())
                val vx = velocityTracker.xVelocity
                val scrollX = scrollX
                val targetPage = if(abs(vx)< minVelocity){
                    if(scrollX>width/2) 1 else 0
                }else{
                    if(vx<0) 1 else 0
                }
                val scrollDistance = if(targetPage == 1) width-scrollX else -scrollX
                overScroller.startScroll(scrollX,0,scrollDistance,0)
                postInvalidateOnAnimation()
            }
        }
        return true
    }

    // 每次调用draw的时候会被调用
    override fun computeScroll() {
        if (overScroller.computeScrollOffset()){
            scrollTo(overScroller.currX,overScroller.currY)
            postInvalidateOnAnimation()
        }
    }
}

文章作者: Lao Wu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Lao Wu !
评论
  目录