我在Android中创建了一个继承自RelativeLayout的自定义视图。在这个视图中是一个OverScroller,用于在触摸事件发生时处理视图的滚动:
class MyCustomView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : RelativeLayout(context, attrs, defStyleAttr) {
constructor(context: Context) : this(context, null, 0)
constructor(context: Context, attrs: AttributeSet) : this(context, attrs, 0)
private val scroller = OverScroller(context, FastOutLinearInInterpolator())
private var currentY = 0
private val gestureDetector = GestureDetectorCompat(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onDown(event: MotionEvent?): Boolean {
// Stop the current scroll animation
scroller.forceFinished(true)
// Invalidate the view
ViewCompat.postInvalidateOnAnimation(this@MyCustomView)
return true
}
override fun onScroll(event1: MotionEvent?, event2: MotionEvent?, distanceX: Float, distanceY: Float): Boolean {
scroller.forceFinished(true)
currentY -= distanceY.toInt()
ViewCompat.postInvalidateOnAnimation(this@MyCustomView)
return true
}
override fun onFling(e1: MotionEvent?, e2: MotionEvent?, velocityX: Float, velocityY: Float): Boolean {
// Stop any scrolling
scroller.forceFinished(true)
scroller.fling(0, currentY, 0, velocityY.toInt(), 0, 0,
-5000 + height, 0)
// Invalidate the view
ViewCompat.postInvalidateOnAnimation(this@MyCustomView)
return true
}
})
@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent?): Boolean {
if (event == null) return false
// Return the value from the gesture detector
return gestureDetector.onTouchEvent(event)
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
// Draw stuff to canvas, using currentY as origin
}
override fun computeScroll() {
// Call to super class method
super.computeScroll()
if (scroller.computeScrollOffset()) {
currentY = scroller.currY
}
// Invalidate the view
ViewCompat.postInvalidateOnAnimation(this@MyCustomView)
}
}
这很好用。接下来,我添加了一个RelativeLayout
视图组来保存一大堆膨胀的细胞。这些单元格是可点击的。现在,当我尝试通过第一次触摸其中一个充气单元格来启动滚动时,单元格会吞下click事件(带有滚动条的父视图永远不会被调用onTouchEvent
因此不会滚动。
需要注意的重要事项:包含单元格的RelativeLayout
视图组是child
的{{1}}视图。
我已尝试在MyCustomView
中覆盖onInterceptTouchEvent
,以便在将触摸事件发送到任一视图之前拦截触摸事件:
MyCustomView
然后我确定触摸事件的操作代码是否为override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
if (event == null) return false
if (event.action == MotionEvent.ACTION_UP) {
if (event.historySize > 0) {
val startY = event.getHistoricalY(0)
val endY = event.getHistoricalY(event.historySize - 1)
val distance = Math.abs(endY - startY).toInt()
if (distance == 0) {
// Consider this a click (so don't swallow it
return false
}
}
}
// Ok this isn't a click, so call this views onTouchEvent
return this.onTouchEvent(event)
}
,如果是,我计算ACTION_UP
和ACTION_DOWN
之间的总距离,如果它是'在一个足够小的范围内,我将其视为点击并调用ACTION_UP
(如果事件在一个单元格上,它将点击一个膨胀的单元格,否则它将最终调用我将处理的super.onInterceptTouchEvent(event)
滚动。如果事件的操作代码不是onTouchEvent
或移动的距离不够小,它将返回ACTION_UP
。
我遇到的问题是我的解决方案无法正常工作,在充气单元格顶部开始滚动时无法启动滚动。
有谁知道我错过了什么?