Ответ 1
-
onTouchEvents()
для групп вложенных представлений можно управлять с помощьюboolean
onInterceptTouchEvent.
Значение по умолчанию для OnInterceptTouchEvent
равно false.
Родительский onTouchEvent
принимается перед дочерним. Если OnInterceptTouchEvent
возвращает false, он отправляет событие движения по цепочке дочернему обработчику onTouchEvent
. Если он возвращает true, родитель будет обрабатывать событие касания.
Однако могут быть случаи, когда мы хотим, чтобы некоторые дочерние элементы управляли onTouchEvent
, а некоторые из них управлялись родительским представлением (или, возможно, родителем родителя).
Это может управляться более чем одним способом.
- Один из способов защиты дочернего элемента от родительского
OnInterceptTouchEvent
заключается в реализации requestDisallowInterceptTouchEvent.
public void requestDisallowInterceptTouchEvent (boolean disallowIntercept)
Это предотвращает управление одним из родительских представлений onTouchEvent
для этого элемента, если элемент имеет обработчики событий.
- Если значение
OnInterceptTouchEvent
равно false, будет вычисляться дочерний элементonTouchEvent
. Если у вас есть методы в дочерних элементах, обрабатывающих различные события касания, любые связанные обработчики событий, которые отключены, возвращают OnTouchEvent родительскому элементу.
Этот ответ:
fooobar.com/questions/22861/... дает хорошую визуализацию того, как проходит распространение сенсорных событий:
parent -> child|parent -> child|parent -> child views.
- Другой способ возвращает переменные значения из
OnInterceptTouchEvent
для родителя.
В этом примере взята из Управление событиями Touch Touch в группе ViewGroup и демонстрирует, как перехватить дочерний элемент onTouchEvent
при прокрутке пользователя.
4а.
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
/*
* This method JUST determines whether we want to intercept the motion.
* If we return true, onTouchEvent will be called and we do the actual
* scrolling there.
*/
final int action = MotionEventCompat.getActionMasked(ev);
// Always handle the case of the touch gesture being complete.
if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
// Release the scroll.
mIsScrolling = false;
return false; // Do not intercept touch event, let the child handle it
}
switch (action) {
case MotionEvent.ACTION_MOVE: {
if (mIsScrolling) {
// We're currently scrolling, so yes, intercept the
// touch event!
return true;
}
// If the user has dragged her finger horizontally more than
// the touch slop, start the scroll
// left as an exercise for the reader
final int xDiff = calculateDistanceX(ev);
// Touch slop should be calculated using ViewConfiguration
// constants.
if (xDiff > mTouchSlop) {
// Start scrolling!
mIsScrolling = true;
return true;
}
break;
}
...
}
// In general, we don't want to intercept touch events. They should be
// handled by the child view.
return false;
}
Изменить: ответить на комментарии.
Это код из той же ссылки, показывающий, как создать параметры прямоугольника вокруг вашего элемента:
4b.
// The hit rectangle for the ImageButton
myButton.getHitRect(delegateArea);
// Extend the touch area of the ImageButton beyond its bounds
// on the right and bottom.
delegateArea.right += 100;
delegateArea.bottom += 100;
// Instantiate a TouchDelegate.
// "delegateArea" is the bounds in local coordinates of
// the containing view to be mapped to the delegate view.
// "myButton" is the child view that should receive motion
// events.
TouchDelegate touchDelegate = new TouchDelegate(delegateArea, myButton);
// Sets the TouchDelegate on the parent view, such that touches
// within the touch delegate bounds are routed to the child.
if (View.class.isInstance(myButton.getParent())) {
((View) myButton.getParent()).setTouchDelegate(touchDelegate);
}