Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This is how I solved the problem: By overriding the Acitivity's onDispatchTouchEvent() method. Any other solution seemed not to work. The good thing about the onDispatchTouchEvent() method is that is always called prior to forwarding any touch events to any other receiver, so you can intercept every single touch event here.</p> <p>If the event is handled somewhere in here (scale or swipe), I return immediately without forwarding the event to the super class, i. e. to the rest of the view hierarchy. If it is not, I forward it to the super class, so other views can handle it, e. g. to detect short or long clicks.</p> <p>There were a few more problems to solve though: 1. If the user begins a scale gesture, I had to cancel any long click detection processes because the receiving view would get the first DOWN event, then nothing anymore (after the second finger comes down and the scaling started), and then spuriously think that a long press is being performed. 2. When a long press was performed and the context menu came up, I had to prevent swipe and scale gesture detection here in dispatchOnTouchEvent() until the next UP event, otherwise swiping and scaling would be performed even though the context menu is there.</p> <p>Quite complicated, but I spent hours and hours and a lot of trial and error, and just could not find any simpler solution. Anyway, handling 1. scale gestures, 2. horizontal swipe gestures, 3. vertical scroll gestures, 4. long clicks and 5. short clicks, all on the same target view(s), is not quite simple a mission to accomplish... </p> <p>Here is the code (relevant parts of it):</p> <pre><code> @Override public boolean dispatchTouchEvent(MotionEvent e) { if (eventInProgress) { // View shall only receive scale gesture event if visible if (targetView.isShown()) scaleGestureDetector.onTouchEvent(e); if (scaleGestureDetector.isInProgress()) motionEventConsumed = true; } if (motionEventConsumed) { if (e.getAction() == MotionEvent.ACTION_UP) motionEventConsumed = false; if (cancelLongPressEvent) { cancelLongPressEvent = false; targetView.cancelLongPress(); } return (true); } // Get the action that was done on this touch event switch (e.getAction()) { case MotionEvent.ACTION_DOWN: { // store the X value when the user's finger was pressed down downXValue = e.getX(); downYValue = e.getY(); cancelLongPressEvent = true; eventInProgress = true; break; } case MotionEvent.ACTION_MOVE: // When having moved by too many x or y pixels, then // cancel any ongoing long klick events if (cancelLongPressEvent &amp;&amp; Math.abs(e.getX() - downXValue) + Math.abs(e.getY() - downYValue) &gt; 40) { targetView.cancelLongPress(); cancelLongPressEvent = false; } break; case MotionEvent.ACTION_UP: { if (eventInProgress) { // Get the X value when the user released his/her finger float deltaX = e.getX() - downXValue; float deltaY = e.getY() - downYValue; if (Math.abs(deltaX) &gt; Math.abs(deltaY) &amp;&amp; Math.abs(deltaX) &gt; 50) { // going backwards: pushing stuff to the right if (deltaX &gt; 0) { flipRight(); return (true); } // going forwards: pushing stuff to the left if (deltaX &lt; 0) { flipLeft(); return (true); } break; } } } } // If event was not handled here, then forward it to parent, // i. e. to view hierarchy return (super.dispatchTouchEvent(e)); } </code></pre> <p>[...]</p> <pre><code>@Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); MenuInflater mi = getMenuInflater(); mi.inflate(R.menu.lztv_context_menu, menu); contextMenuTargetView = v; eventInProgress = false; } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload