您的位置:首页 > 移动开发 > Android开发

android手势事件传递(实例:下拉刷新)

2015-09-25 11:02 411 查看
先看看api中的解释

分发事件

public boolean dispatchTouchEvent (MotionEvent ev)
Added in API level 1

Pass the touch screen motion event down to the target view, or this view if it is the target.
把触摸屏幕的手势传递到传递到目标的位置。如果当前view是目标,则传递到当前。

Parameters
evThe motion event to be dispatched.
被传递的手势事件

Returns

True if the event was handled by the view, false otherwise.

如果事件被本viewgroup处理则返回true(事件被传递到上一级),否则返回false。

拦截事件(怎么这么长。。。。)

public boolean onInterceptTouchEvent (MotionEvent ev)
Added in API level 1

Implement this method to intercept all touch screen motion events. This allows you to watch events as they are dispatched to your children, and take ownership of the current gesture at any
point.
继承这个方法以拦截所有的手势操作。这允许你在任何情况下监视手势事件是否传递给子view,并获得手势的所有权。
Using this function takes some care, as it has a fairly complicated interaction with
View.onTouchEvent(MotionEvent)
,
and using it requires implementing that method as well as this one in the correct way. Events will be received in the following order:
因为和View.onTouchEvent(MotionEvent)有着复杂的相互作用,使用时需要注意。事件将会以如下的顺序接收:

You will receive the down event here. 接收到down事件
The down event will be handled either by a child of this view group, or given to your own onTouchEvent() method to handle; this means you should implement onTouchEvent() to return true, so you will continue to see the rest
of the gesture (instead of looking for a parent view to handle it). Also, by returning true from onTouchEvent(), you will not receive any following events in onInterceptTouchEvent() and all touch processing

must happen in onTouchEvent() like normal. down事件将被当前view也被子view处理,或者被拦截给自己的onTouchEvent() 处理。这意味着你需要继承onTouchEvent()并return true(而不是传递给父view处理),此后将不再拦截,你可以像往常一样处理onTouchEvent()
For as long as you return false from this function, each following event (up to and including the final up) will be delivered first here and then to the target's onTouchEvent(). 如果该ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return
false,那么后续的move, up等事件将继续会先传递给该ViewGroup,之后才和down事件一样传递给最终的目标view的onTouchEvent()处理。
If you return true from here, you will not receive any following events: the target view will receive the same event but with the action
ACTION_CANCEL
,
and all further events will be delivered to your onTouchEvent() method and no longer appear here. 如果最终需要处理事件的view的onTouchEvent()返回了false,那么该事件将被传递至其上一层次的view的onTouchEvent()处理。
如果最终需要处理事件的view 的onTouchEvent()返回了true,那么后续事件将可以继续传递给该view的onTouchEvent()处理。

Parameters
evThe motion event being dispatched down the hierarchy.
Returns

Return true to steal motion events from the children and have them dispatched to this ViewGroup through onTouchEvent(). The current target will receive an ACTION_CANCEL event, and no further messages will be delivered here.

下拉刷新

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if(mListView.getFirstVisiblePosition()==0){
        /**
         * 当listview在顶部时,不想让listview的子view进行手势事件的的处理。所以进行拦截
         */
        View firstView = mListView.getChildAt(mListView.getFirstVisiblePosition());
        if(firstView.getY()>=0){
            return true;
        }
    }
    return false;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            oldY = event.getY();
            return true;
        case MotionEvent.ACTION_MOVE:
            float y = event.getY();
            float distance = y-oldY;
            mListView.setTranslationY(distance+mListView.getTranslationY());
            oldY = y;
            invalidate();
            return true;
        case MotionEvent.ACTION_UP:
            ObjectAnimator.ofFloat(mListView,"translationY",mListView.getTranslationY(),0).setDuration(300).start();
            return true;

    }
    return super.onTouchEvent(event);
}


1、基础知识

(1) 所有 Touch 事件都被封装成了 MotionEvent 对象,包括 Touch 的位置、时间、历史记录以及第几个手指(多指触摸)等。

(2) 事件类型分为 ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,每个事件都是以 ACTION_DOWN 开始 ACTION_UP 结束。

(3) 对事件的处理包括三类,分别为传递——dispatchTouchEvent()函数、拦截——onInterceptTouchEvent()函数、消费——onTouchEvent()函数和 OnTouchListener

2、传递流程

(1) 事件从 Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的 View(ViewGroup)开始一直往下(子 View)传递。子 View 可以通过 onTouchEvent()对事件进行处理。

(2) 事件由父 View(ViewGroup)传递给子 View,ViewGroup 可以通过 onInterceptTouchEvent()对事件做拦截,停止其往下传递。

(3) 如果事件从上往下传递过程中一直没有被停止,且最底层子 View 没有消费事件,事件会反向往上传递,这时父 View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到 Activity 的 onTouchEvent()函数。

(4) 如果 View 没有对 ACTION_DOWN 进行消费,之后的其他事件不会传递过来。

(5) OnTouchListener 优先于 onTouchEvent()对事件进行消费。

上面的消费即表示相应函数返回值为 true。

更多请直接阅读 PDF 英文原文:Mastering the Android
Touch System


示例代码:Demo@Github

附上两张原文中流程图:

(1) View 不处理事件流程图





(2) View 处理事件流程图







内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: