measureChildren(widthMeasureSpec, heightMeasureSpec) 将子View宽高设为同等大小
parent.requestDisallowInterceptTouchEvent(true) 当前若是滑动控件,且拦截子View,除了子View cancel,还要通知上一级View不再拦截,如果在滑动控件,触摸到子View则父View会收到InterTouch,子View收到TouchDown,而父View收不到TouchDown,scrollTo参数是相反
.coerceAtLeast(0) 上限 .coerceAtMost(width)下限
VelocityTracker 记速器
code
package com.example.myapplication.view
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.ViewConfiguration
import android.view.ViewGroup
import android.widget.OverScroller
import androidx.core.view.children
import kotlin.math.abs
class TwoPager(context: Context, attrs: AttributeSet) : ViewGroup(context, attrs) {
var downX = 0f
var downY = 0f
var downScrollX = 0f
var scrolling = false
var overScroller: OverScroller = OverScroller(context)
var viewConfiuration = ViewConfiguration.get(context)
var velocityTracker = VelocityTracker.obtain()
var minVelocity = viewConfiuration.scaledMinimumFlingVelocity //最小快滑
var maxVelocity = viewConfiuration.scaledMaximumFlingVelocity //最大快滑
var pagingSlop = viewConfiuration.scaledPagingTouchSlop
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
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 onInterceptHoverEvent(event: MotionEvent): Boolean {
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
velocityTracker.clear()
}
velocityTracker.addMovement(event)
var result = false
when (event.actionMasked) {
MotionEvent.ACTION_DOWN -> {
scrolling = false
downX = event.x
downY = event.y
downScrollX = scrollX.toFloat()
}
MotionEvent.ACTION_MOVE -> if (!scrolling) {
val dx = downX - event.x
if (abs(dx) > pagingSlop) {
scrolling = 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 = (downX - event.x + downScrollX).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(getScrollX(), 0, scrollDistance, 0) //给一个位置,然后自动计算
postInvalidateOnAnimation()
}
}
return true
}
//draw调用 这个也会调用
override fun computeScroll() {
if (overScroller.computeScrollOffset()) {
scrollTo(overScroller.currX, overScroller.currY)
postInvalidateOnAnimation()
}
}
}