I'm pretty new to Android app development, and I've been playing around with swipe gestures using Android's SimpleOnGestureListener and a ViewFlipper. There are 3 children of the ViewFlipper, and each is a ScrollView. They're all dynamically populated when the Activity loads, and they don't change after that. The ScrollView is where the SimpleOnGestureListeners are attached.
Here's the layout I'm using:
+ ViewFlipper
++ ScrollView (x3, по одному на каждую страницу, каждая со следующим:)
+++ LinearLayout (вертикальный)
++++ TextView
++++ TableLayout (динамически заполненный с TableRows)
++++ View
Я расширил метод onFling общим учебным кодом, который вы можете найти в любом месте онлайн, и он прекрасно работает - за исключением случаев, когда один из ScrollViews не содержит достаточно контента для прокрутки.
Я сузил проблему до определения касания, переопределив и вызвав super для каждого из методов SimpleOnGestureListener, чтобы добавить вывод в журнал.
Когда я пролистываю прокручиваемую страницу, я получаю что-то полное «inClick», «onScroll», «onFling» и т. Д. На слишком короткой странице для прокрутки я получаю «inClick», «onShowPress». «в onLongPress», и это только в том случае, если я касаюсь содержимого внутри дочерних элементов слишком короткого прокрутки - если я касаюсь в другом месте, я вообще не получаю никаких событий.
Идеи о том, что не так, или как определить жест смахивания независимо от того, насколько велик ScrollView?
РЕДАКТИРОВАТЬ: я определил, что при запуске этого на эмуляторе Android 2.2, в отличие от эмулятора Android 2.1u1 DroidX, который я использовал, это уходит. Это воспроизводимо в разных средах.
У меня есть еще кое-что об этом; кажется, что onInterceptTouchEvent не вызывается для каждого события движения, когда представление прокрутки содержится в флиппере (или в WorkspaceView).
В частности, поведение, которое я обнаружил при изменении другого класса представления, чтобы исправить эту самую проблему (это не было уникальным для плавников): обратите внимание, что это только Android 2.1:
Если представление прокрутки достаточно длинное для прокрутки, событие движения ACTION_DOWN перехватывается ScrollView, и каждое последующее событие ACTION_MOVE проходит через onInterceptTouchEvent флиппера, где оно перехватывается и обрабатывается соответствующим образом. В Android 2.2 это происходит независимо от длины прокрутки.
Назад к 2.1: Если представление прокрутки недостаточно длинное для прокрутки, событие движения ACTION_DOWN не перехватывается просмотром прокрутки, а вместо этого приходит вернуться к onTouchEvent флиппера. Все последующие события ACTION_MOVE того же самого жеста пропускают функцию onInterceptTouchEvent и переходят прямо к функции onTouchEvent!
Я решил, что нужно использовать функциональность, имеющуюся в onTouchEvent для событий ACTION_MOVE, и выполнить ее рефакторинг в свой метод. Таким образом, У меня может быть вызов onTouchEvent onInterceptTouchEvent, за которым следуют эти функции, если он обнаруживает, что событие ранее было необработанным.
case MotionEvent.ACTION_MOVE:
if (touchState == TOUCH_STATE_SCROLLING) {
handleScrollMove(ev);
} else {
// Log.d("workspace","caught a move touch event but not scrolling");
//NOTE: We will never hit this case in Android 2.2. This is to fix a 2.1 bug.
//We need to do the work of interceptTouchEvent here because we don't intercept the move
//on children who don't scroll.
Log.d("workspace","handling move from onTouch");
if(onInterceptTouchEvent(ev) && touchState == TOUCH_STATE_SCROLLING){
handleScrollMove(ev);
}
}
break;
Это из WorkspaceView.java (модификация Android Workspace.java, найденная в проекте andro-views в коде Google, и теперь здесь: Горизонтальная прокрутка «табуляции» между представлениями ). В случае, когда мы получаем событие перемещения и прокручиваем (что происходит, только если мы сознательно решили перехватить его - т. Е. Оно установлено в функции перехвата, поэтому мы уже были в функции перехвата), мы выполняем поведение движения мы желаем. Если мы получаем событие перемещения здесь и не прокручиваем, то мы отправляем событие обратно через onIntercept, а затем проверяем, настроена ли сейчас прокрутка. Если это так, мы выполняем действие.
Это не элегантно, но работает!
Попробуйте установить android: fillViewport = "true"
в XML макета для каждого из ScrollView
s. Это говорит о том, что ScrollView
должен быть такого же размера, как и представление, в котором он содержится.