Android 触摸事件分发

来源:互联网 发布:画婚车路线图的软件 编辑:程序博客网 时间:2024/05/21 16:57

看了N多文章介绍事件分发,不如自己写一个例子更透彻。
知识点提要:
1.View 具有的方法:
dispatchTouchEvent(MotionEvent event);(分发)true—->消费
onTouchEvent(MotionEvent event);(触摸)
2.ViewGroup 具有的方法:
dispatchTouchEvent(MotionEvent event);(分发)true—->消费
onTouchEvent(MotionEvent event);(触摸)
onInterceptTouchEvent(MotionEvent ev);(拦截)
3.Activity具有的方法:
dispatchTouchEvent(MotionEvent event);(分发)true—->消费

根据以上,上主要代码:
MainActivity重写onCreate 和dispatchTouchEvent:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.myRelativeLayout).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "myRelativeLayout.onClick");
}
});
findViewById(R.id.myTextView).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "myTextView.onClick");
}
});
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.d(TAG, "dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}

MyRelativeLayout重写onTouchEvent(),onInterceptTouchEvent(),dispatchTouchEvent()。

public class MyRelativeLayout extends RelativeLayout {    public String TAG = getClass().getName(); public MyRelativeLayout(Context context) {        super(context);    }    public MyRelativeLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    public MyRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        Log.d(TAG, "onTouchEvent");        return super.onTouchEvent(event);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        Log.d(TAG, "onInterceptTouchEvent");        return super.onInterceptTouchEvent(ev);       // return true;    }    @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        Log.d(TAG, "dispatchTouchEvent");        return super.dispatchTouchEvent(ev);    }}

MyTextView 重写dispatchTouchEvent(MotionEvent event),
onTouchEvent(MotionEvent event);

public class MyTextView extends TextView {    public String TAG = getClass().getName();    public MyTextView(Context context) {        super(context);    }    public MyTextView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);    }    public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        Log.d(TAG, "onTouchEvent");        return super.onTouchEvent(event);    }    @Override    public boolean dispatchTouchEvent(MotionEvent event) {        Log.d(TAG, "dispatchTouchEvent");        return super.dispatchTouchEvent(event);    }}

1.触摸MyTextView:
MainActivity: dispatchTouchEvent–down
MyRelativeLayout:dispatchTouchEvent–down
MyRelativeLayout: onInterceptTouchEvent–down
MyTextView: dispatchTouchEvent–down
MyTextView: onTouchEvent–down
MainActivity: dispatchTouchEvent–up
MyRelativeLayout: dispatchTouchEvent–up
MyRelativeLayout: onInterceptTouchEvent–up
MyTextView: dispatchTouchEvent–up
MyTextView: onTouchEvent–up
MainActivity: myTextView.onClick

2.修改MyRelativeLayout onInterceptTouchEvent 返回true结果:
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onInterceptTouchEvent
MyRelativeLayout: onTouchEvent
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onTouchEvent
MainActivity: myRelativeLayout.onClick

3.修改MyRelativeLayout dispatchTouchEvent返回true结果:
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent

4.修改MyTextView dispatchTouchEvent返回true结果:
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onInterceptTouchEvent
MyTextView: dispatchTouchEvent
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onInterceptTouchEvent
MyTextView: dispatchTouchEvent

5.修改MyRelativeLayout dispatchTouchEvent返回false结果:
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MainActivity: dispatchTouchEvent

6.修改MyTextView dispatchTouchEvent返回false结果:
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onInterceptTouchEvent
MyTextView: dispatchTouchEvent
MyRelativeLayout: onTouchEvent
MainActivity: dispatchTouchEvent
MyRelativeLayout: dispatchTouchEvent
MyRelativeLayout: onTouchEvent
MainActivity: myRelativeLayout.onClick

对比1和2,结论一:父View的onInterceptTouchEvent 返回true则touch不会再传递给子View,该事件由父View处理。
对比1和3、4,结论二:父View的dispatchTouchEvent 返回true,则touch不会再往下传递,up事件和down事件一样,父View接收up事件。
对比1和3、5,结论三:父View的dispatchTouchEvent 返回false,则touch不会再往下传递,up事件也不会再交给该父View处理。
对比1和3、5、6,结论四:子View的dispatchTouchEvent 返回false,则touch不会再往下传递,up事件也不会交给该子View处理,该事件交给父View处理,且不会up事件传递不会调用该父View的onInterceptTouchEvent 事件。
对比1和2、6、结论五:父View的onInterceptTouchEvent 返回true和子View的dispatchTouchEvent 返回false效果类似,区别只在于后者会执行一次dispatchTouchEvent 事件。
对比1和4、6,结论六:子View的dispatchTouchEvent返回true和false区别:返回true,不会执行父View的onTouchEvent方法,up事件父View会执行onInterceptTouchEvent事件;返回false,会执行父View的onTouchEvent方法,up事件父View不会执行onInterceptTouchEvent事件。
结论不太好记,
总结一下就是,父dispatchTouchEvent 返回false ,事件不会传递给子View,该事件会被父View的父View来处理调用onTouchEvent方法;
子View dispatchTouchEvent 返回true,该事件会被丢弃,不会调用onTouchEvent方法,touch事件会被丢弃,想继续传递应该返回super.dispatchTouchEvent ;
父View 调用onInterceptTouchEvent 子View不会接受到该事件,由该父View处理,up事件不会受到影响。

原创粉丝点击