Я создал пользовательский вид в 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
для хранения нагрузки надутых ячеек. Эти ячейки доступны для просмотра. Теперь, когда я пытаюсь инициировать свиток с первым касанием на одной из этих завышенных ячеек, ячейка проглатывает событие щелчка (родительское представление с помощью скроллера никогда не получает его onTouchEvent
и поэтому не прокручивается).
Важно отметить: группа просмотра RelativeLayout
которая содержит ячейки, представляет собой child
вид 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
или перемещенное расстояние не было достаточно маленьким, оно вернет this.onTouchEvent(event)
.
Проблема, с которой я сталкиваюсь, заключается в том, что мое решение не работает, прокрутка по-прежнему не может быть инициирована при запуске свитка поверх накаченной ячейки.
Кто-нибудь знает, что мне не хватает?