关于android 的事件分发机制

来源:互联网 发布:新浪微博数据2017 编辑:程序博客网 时间:2024/05/21 17:36

android 关于事件分发的三个方法:


dispatchTouchEvent代表事件分发,返回值为true或false都表示不分发,返回super.dispatchTouchEvent表示将事件分发下去


onInterceptTouchEven代表事件拦截(ViewGroup特有的事件),返回值为true表示拦截事件,交给ViewGroup的OnTouchEvent处理,返回值为false表示交给子view的dispatchTouchEvent进行事件分发


onTouchEvent代表事件消费,返回值为true表示消费,返回值为false表示不消费,该事件将交给父控件的onTouchEvent进行处理


首先在dispatchTouchEvent中最先执行的就是onTouch方法,而onClick的调用是在onTouchEvent(event)方法中,因此onTouch肯定是要优先于onClick执行的。

而如果在onTouch方法里返回了true,就会让dispatchTouchEvent方法直接返回true,不会再继续往下执行。


下附代码说明,有兴趣的可以直接跑一下验证

public class MainActivity extends AppCompatActivity {    private static final String TAG = "MainActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        LinearLayout ll = (LinearLayout) findViewById(R.id.ll);        Button btn = (Button) findViewById(R.id.btn);        ll.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Log.d(TAG, "LinearLayout: ");            }        });        ll.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                return false;            }        });        btn.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Log.d(TAG, "Button: ");            }        });        btn.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                return false;            }        });    }}


以上面这段代码为例子,如果我重写了LinearLayout中的onInterceptTouchEvent并返回true

@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {    Log.e(TAG, "MyLayout onInterceptTouchEvent default return " + super.onInterceptTouchEvent(ev));    return super.onInterceptTouchEvent(ev);}
改成

@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {    Log.e(TAG, "MyLayout onInterceptTouchEvent default return " + super.onInterceptTouchEvent(ev));    return true;}
然后添加一句代码

btn.setOnClickListener(new View.OnClickListener() {    @Override    public void onClick(View v) {        Log.d(TAG, "Button: ");        btn.setText( "Button: ");    }});

运行之后,btn不会触发点击事件,因为事件被MyLayout拦截了,转而触发MyLayout的点击事件,如果这个时候设置onTouch事件返回true,那么连MyLayout的点击事件也不会触发,因为OnTouchEvent没有接受到事件,在OnTouchEvent内部被调用的OnClick事件自然也不会触发


最后再补充一句,ViewGroup和View都有dispatchTouchEvent方法,如果在ViewGroup里面dispatchTouchEvent的返回值为true,那么事件就不会分发下去,在我这个例子里面就是没有触发btn的点击事件


原创粉丝点击