视图之间尴尬的触摸事件传播 [英] Awkward touch event propagation between views

查看:168
本文介绍了视图之间尴尬的触摸事件传播的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个图库的ImageView S和的ImageView s为捏缩放和平移。我的目标是,一旦一个的ImageView 再也不能转化为左/右,在图库将滚动。所以有时的ImageView 需要处理的触摸事件,有时图库需要处理的触摸事件。我在我的的ImageView 逻辑的的onTouchEvent 方法时,我想切换到发生,但我m如果您意外的结果。我会解释这个问题后,我告诉我的code:

I have a Gallery full of ImageViews, and the ImageViews are pinch-zoomable and translatable. My goal is that once an ImageView can no longer translate to the left/right, the Gallery will scroll. So sometimes the ImageView needs to handle the touch event, sometimes the Gallery needs to handle the touch event. I have logic in my ImageView's onTouchEvent method for when I want the hand-off to occur, but I'm getting unexpected results. I'll 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;
}

这是我的图库。我重写的onTouchEvent 只是它接收触摸事件时显示。

And here's my Gallery. I overwrote onTouchEvent just to show when it was receiving touch events.

// SwipeGallery.java

@Override
public boolean onTouchEvent( MotionEvent event ) {

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

所以,当我加载了活动,我试图从右向左轻扫。该逻辑直通的议案事件立即触发,但这里是我的日志输出。

So when I load up the activity, i attempt to swipe from right to left. The logic to pass-through the motion event is immediately triggered, but here's my log output.

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.

我第二次刷卡从右到左,我得到这样的:

The SECOND time I swipe right to left, I get this:

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!

第一运动事件中的ImageView的总处理,第二移动事件画廊总是处理的这种模式继续下去永远(新的ImageView被做在画廊的每个位置,这也就是为什么 isPassThroughTouchEvent() 返回false 3日,5日,等时间)。那么究竟我在这里丢失?我以为返回false将会传播触摸事件,直到它被处理,但图库将不把它的第一次,但它的第二个?这是没有意义的我。任何人有什么想法?谢谢你。

This pattern of "1st motion event the imageview always handles, 2nd motion event the gallery always handles" continues on forever (A new imageview gets made for each position in the gallery which is why isPassThroughTouchEvent() returns false the 3rd, 5th, etc time). So what exactly am I missing here? I thought returning false would propagate the touch event until it was handled, but the Gallery won't take it the first time, but it does the second? This makes no sense to me. Anyone have any ideas? Thanks.

推荐答案

在一个观点上的向下返回true(ACTION_DOWN <$ C C $>)移动事件,这种观点是锁定作为触摸运动目标。这意味着它将接收后续的移动事件到最终向上事件不管它发生在哪里,屏幕上(见本),除非如果其父<一个href="http://developer.android.com/reference/android/view/ViewGroup.html#onInterceptTouchEvent%28android.view.MotionEvent%29"相对=nofollow>希望和<一href="http://developer.android.com/reference/android/view/ViewGroup.html#requestDisallowInterceptTouchEvent%28boolean%29"相对=nofollow>允许拦截事件。

When a view returns true on the down (ACTION_DOWN) motion event, that view is "locked in" as the touch motion target. Which means that it will receive the subsequent motion events up to the final up event regardless of where it happens on the screen (see this thread), unless if its parent wants and allowed to intercept the event.

要解释你的情况:

  1. 在第一次刷卡,你的的ImageView 处理的上下运动,这使得它的运动目标(见日志)。这意味着所有的后续动作事件将交付给它,因为你的图库不拦截事件,其的onTouchEvent 处理程序将不会被调用。

  1. On the first swipe, your ImageView handled the down motion which makes it the motion target (see the log). That means all subsequent motion events will be delivered to it, and since your Gallery does not intercept the events, its onTouchEvent handler will not be called.

在第二次刷卡,你的的ImageView 不处理的上下运动(日志与中显示即时得到TOUCH!+即时返回false !),并通过事件到下一个处理程序,在这种情况下,图库这将运行的onTouchEvent 处理程序。默认情况下图库总是处理关闭事件,这在将其锁定为运动目标。

On the second swipe, your ImageView don't handle the down motion (shown in the log with "IM GETTING TOUCH!" + "IM RETURNING FALSE!") and passed the event to the next handler, in this case the Gallery which will run its onTouchEvent handler. By default Gallery always handle the down event, which locks it in as the motion target.

这篇关于视图之间尴尬的触摸事件传播的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆