Awkward event of touch event between views

I have Gallery , full ImageView s, and ImageView is compressed and translationally scaled. My goal is that after the ImageView can no longer translate left / right, the Gallery scrolls. Therefore, sometimes ImageView must handle the touch event, sometimes Gallery must handle the touch event. I have logic in my ImageView onTouchEvent method when I want the transfer to complete, but I get unexpected results. I will explain the problem after I show my code:

 // PinchZoomImageView.java @Override public boolean onTouchEvent( MotionEvent event ) { Log.i( "PinchZoomImageView", "IM GETTING TOUCHED!" ); if ( isPassThroughTouchEvent() ) { Log.i( "PinchZoomImageView", "IM RETURNING FALSE!" ); return false; } getScaleDetector().onTouchEvent( event ); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { final float x = event.getX(); final float y = event.getY(); setLastTouchX( x ); setLastTouchY( y ); setActivePointerId( event.getPointerId( 0 ) ); break; } case MotionEvent.ACTION_MOVE: { final int pointerIndex = event.findPointerIndex( getActivePointerId() ); final float x = event.getX( pointerIndex ); final float y = event.getY( pointerIndex ); // Only move if the ScaleGestureDetector isn't processing a gesture. if ( !getScaleDetector().isInProgress() ) { if ( isDetectMovementX() ) { final float dx = x - getLastTouchX(); setPosX( getPosX() + dx ); } if ( isDetectMovementY() ) { final float dy = y - getLastTouchY(); setPosY( getPosY() + dy ); } invalidate(); } setLastTouchX( x ); setLastTouchY( y ); if ( isAtXBound() && !isPassThroughTouchEvent() ) { setPassThroughTouchEvent( true ); } break; } case MotionEvent.ACTION_UP: { setActivePointerId( INVALID_POINTER_ID ); break; } case MotionEvent.ACTION_CANCEL: { setActivePointerId( INVALID_POINTER_ID ); break; } case MotionEvent.ACTION_POINTER_UP: { final int pointerIndex = ( event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK ) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; final int pointerId = event.getPointerId( pointerIndex ); if ( pointerId == getActivePointerId() ) { // This was our active pointer going up. Choose a new // active pointer and adjust accordingly. final int newPointerIndex = pointerIndex == 0 ? 1 : 0; setLastTouchX( event.getX( newPointerIndex ) ); setLastTouchY( event.getY( newPointerIndex ) ); setActivePointerId( event.getPointerId( newPointerIndex ) ); } break; } } return true; } 

And here is my Gallery . I onTouchEvent to show when it received touch events.

 // SwipeGallery.java @Override public boolean onTouchEvent( MotionEvent event ) { Log.i( "SwipeGallery", "IM GETTING TOUCHED!" ); return super.onTouchEvent( event ); } 

So when I load activity, I try to scroll from right to left. The logic for transmitting a motion event starts immediately, but here is my exit to the log.

 08-02 10:04:47.097: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.179: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.179: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.179: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 08-02 10:04:47.230: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.230: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 08-02 10:04:47.230: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.230: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 08-02 10:04:47.245: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.245: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 08-02 10:04:47.261: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.261: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 08-02 10:04:47.277: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.277: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 08-02 10:04:47.296: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.296: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 08-02 10:04:47.312: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.312: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 08-02 10:04:47.327: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.327: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 08-02 10:04:47.343: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.343: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 08-02 10:04:47.360: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:04:47.360: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! ....etc. 

SECOND time, when I scroll right to left, I get the following:

 08-02 10:27:31.573: INFO/PinchZoomImageView(17189): IM GETTING TOUCHED! 08-02 10:27:31.573: INFO/PinchZoomImageView(17189): IM RETURNING FALSE! 08-02 10:27:31.573: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 08-02 10:27:31.636: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 08-02 10:27:31.636: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 08-02 10:27:31.683: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 08-02 10:27:31.933: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 08-02 10:27:31.964: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 08-02 10:27:31.999: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 08-02 10:27:32.034: INFO/SwipeGallery(17189): IM GETTING TOUCHED! 

This template of the β€œ1st motion event that always processes the image, the second motion event that the gallery always processes” continues forever (a new image is viewed for each position in the gallery, therefore isPassThroughTouchEvent() returns false 3rd, 5th, and etc.). So what am I missing here? I thought returning false would propagate the touch event until it is processed, but Gallery will not accept it for the first time, but is it second? It makes no sense to me. Does anyone have any ideas? Thanks.

+6
source share
1 answer

When a view returns true on a down event ( ACTION_DOWN ), that view is "locked" as the target of the touch move. This means that he will receive subsequent motion events until the final event, no matter where it occurs on the screen (see. This thread ), if only his parent wants and is allowed to intercept the event.

To explain your situation:

  • The first time you scroll, your ImageView processes a downward motion, which makes it the target of the motion (see log). This means that all subsequent motion events will be delivered to it, and since your Gallery does not intercept events, its onTouchEvent handler onTouchEvent not be called.

  • During the second scroll, your ImageView does not handle downward movement (shown in the log with "IM GETTING TOUCH!" + "IM RETURNING FALSE!") And passed the event to the next handler, in this case Gallery , which will fire its onTouchEvent handler. By default, Gallery always processes the down event, which blocks it as the target of the movement.

+3
source

Source: https://habr.com/ru/post/894117/


All Articles