#android #event-handling #touch
#Android #обработка событий #коснитесь
Вопрос:
У меня есть проект, использующий ViewPager, который работает правильно: я могу переходить от просмотра к просмотру, щелкая влево и вправо.
На одной странице ViewPager у меня есть пользовательский вид, и я пытаюсь добавить под ним другое представление (LinearLayout), которое чувствительно к касанию и которое не будет «отображать» ViewPager. Вот так:
<LinearLayout >
<myView />
<LinearLayout> // The touch sensitive region
</LinearLayout>
</LinearLayout>
После того, как мой view был увеличен и добавлен в ViewPager, я вызываю setOnTouchListener(), чтобы присоединить слушателя к внутреннему LinearLayout. Слушатель возвращает «true».
К сожалению, когда я перемещаюсь по горизонтали в этом представлении, я перехожу на другую страницу. Я получаю следующие события: ACTION_DOWN, ACTION_MOVE (n раз) и, наконец, ACTION_CANCEL. Хотя я оставался в пределах представления.
Похоже, что событие поднялось по иерархии представлений и обработано ViewPager.
Есть ли логическое объяснение такому поведению?
Ответ №1:
Я нашел обходной путь, перехватывая события на уровне активности, переопределяя dispatchTouchEvent() .
Там я вызываю super.dispatchTouchEvent() для обработки всех событий, если пользователь не касается моего сенсорного представления. Я проверяю, находится ли пользователь на правильной странице и в нужном месте. В этом случае я сам обрабатываю событие.
@Override
public boolean dispatchTouchEvent (MotionEvent ev) {
if ( pager.getCurrentPosition()!=0 ) { // Test ViewPager page
super.dispatchTouchEvent(ev);
}
else {
int[] xy = new int[2];
findViewById(R.id.myTouchControl).getLocationOnScreen(xy);
int topOfView = xy[1];
if ( ev.getY() > topOfView ) {
// Custom processing
...
} else {
// Standard processing
super.dispatchTouchEvent(ev);
}
}
return false;
}
Ответ №2:
Нет необходимости переопределять dispatchTouchEvent(). Вместо этого в событии ACTION_DOWN используйте View.getParent().requestDisallowInterceptTouchEvent(true)
.
requestDisallowInterceptTouchEvent(true)
запрашивает родительский просмотр (ViewPager) не перехватывать это конкретное событие касания. Этот флаг будет снят после завершения MotionEvent, поэтому вы должны вызвать его в ACTION_DOWN.