视图之间的尴尬触摸事件传播

时间:2011-08-02 15:32:44

标签: android android-gallery

我有GalleryImageView个,ImageView是可缩放的,可翻译的。我的目标是,ImageView无法再转换为左/右,Gallery将滚动。因此有时ImageView需要处理触摸事件,有时Gallery需要处理触摸事件。我在ImageView的{​​{1}}方法中有逻辑,因为当我希望发生切换时,我会得到意想不到的结果。我在展示代码后会解释这个问题:

onTouchEvent

这是我的// 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; } 。我覆盖了Gallery只是为了表明接收触摸事件的时间。

onTouchEvent

所以当我加载活动时,我会尝试从右向左滑动。传递动作事件的逻辑立即被触发,但这是我的日志输出。

// SwipeGallery.java

@Override
public boolean onTouchEvent( MotionEvent event ) {

    Log.i( "SwipeGallery", "IM GETTING TOUCHED!" );
    return super.onTouchEvent( event );
}

第二次我从右向左滑动,我明白了:

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.

“imageview始终处理的第一个动作事件,画廊始终处理的第二个动作事件”的这种模式将永远持续下去(为图库中的每个位置创建一个新的imageview,这就是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! 返回false的原因,第5等时间)。那么我到底错过了什么?我认为返回false会传播触摸事件直到它被处理,但是isPassThroughTouchEvent()不会第一次接受它,但它会在第二次执行吗?这对我来说毫无意义。有人有主意吗?感谢。

1 个答案:

答案 0 :(得分:3)

当视图在向下(ACTION_DOWN)运动事件中返回true时,该视图将“锁定”为触摸运动目标。这意味着,无论屏幕在屏幕上发生什么,它都会收到后续动作事件(请参阅此thread),除非其父级wantsallowed为拦截事件。

解释你的情况:

  1. 在第一次滑动时,ImageView处理了向下运动,使其成为运动目标(请参阅日志)。这意味着所有后续动作事件都将被传递给它,并且由于您的Gallery不拦截事件,因此不会调用其onTouchEvent处理程序。

  2. 在第二次滑动时,ImageView不处理向下运动(在日志中显示“IM GETTING TOUCH!”+“IM RETURNING FALSE!”)并将事件传递给下一个处理程序,在这种情况下是Gallery,它将运行其onTouchEvent处理程序。默认情况下,Gallery始终处理向下事件,该事件将其锁定为运动目标。