Android的事件响应机制
1:View的事件响应机制(控件:如TextView,ImageView,Button等)
在执行onTouchListener方法时候,(view这里代表为控件)
view.setOnTouchListener(newOnTouchListener(){
@Override
publicbooleanonTouch(View v,MotionEvent event){
returnfalse;
}
});
事件分发的时候会执行publicbooleandispatchTouchEvent(MotionEvent event)
a:先进行if判断
if(li!=null&&li.mOnTouchListener!=null&&(mViewFlags&ENABLED_MASK)==ENABLED
&&li.mOnTouchListener.onTouch(this,event)){
returntrue;
}
returnonTouchEvent(event);
li就是OnTouchListener的实现类,不为null,第二个条件判断控件是否可用,一般恒成立,主要就看第三个条件了。
return true:就代表响应所有事件。
return false:就会执行onTouchEvent方法了。
b:setOnTouchListener方法返回了false
在onTouchEvent方法中,如果控件具备点击事件,在action_up中回调执行onClick的点击事件,并且返回true,响应所有事件。如果控件不具备点击事件,就会返回false,也进入不了switch中。
2:ViewGroup的事件响应机制
ViewGroup的事件响应机制主要分为2部分:1:ViewGroup拦截了事件,2:ViewGroup没有拦截事件
/*
* return true拦截了事件
* return false没有拦截事件,往内部传递
*/
@Override
publicbooleanonInterceptTouchEvent(MotionEvent ev){
returntrue;
}
1:拦截了事件:
那么ViewGroup就会去处理事件,在源码中最后还是调用View的dispatchTouchEvent方法,由其决定是否响应,onTouchEventListener中return了true,就响应了事件,return了false,那么就去判断当前控件(布局)是不是可以被点击,测试了一次ListView,ListView点击的时候响应了事件。ListView无论是不是中断,都会由View的dispatchTouchEvent方法决定,ListView可以被点击。
2:没有拦截事件:
最外层的ViewGroup先捕获到事件,计算出点击的位置,遍历自己的孩子,传递给对应的ViewGroup,然后第二层是不是拦截啊?不拦截,继续遍历,找到具体点击的地方的控件view。
控件view会去通过View的dispatchTouchEvent方法的返回值判断是不是响应了点击事件,return true;响应了,那么结束了。如果return false;了没有响应,那么事件会向回传递,自己的父亲回去尝试响应了。同样,通过dispatchTouchEvent来进行决定是不是响应了事件。
示例代码:
1:拦截事件
自定义控件
publicclassMyLinearLayoutextendsLinearLayout{
publicMyLinearLayout(Context context,AttributeSet attrs){
super(context,attrs);
}
@Override
publicbooleanonInterceptTouchEvent(MotionEvent ev){
returntrue;
}
}
MainActivity
publicclassMainActivityextendsActivity{
privateLinearLayoutmy_ll;
privateButtonbutton;
privateTextViewtextView;
@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
my_ll=(LinearLayout)findViewById(R.id.my_ll);
button=(Button)findViewById(R.id.button);
textView=(TextView)findViewById(R.id.text);
my_ll.setOnTouchListener(newOnTouchListener(){
@Override
publicbooleanonTouch(View v,MotionEvent event){
System.out.println("Linearlayout:"+event.getAction());
returntrue;
}
});
textView.setOnTouchListener(newOnTouchListener(){
@Override
publicbooleanonTouch(View v,MotionEvent event){
System.out.println("TextView:"+event.getAction());
returnfalse;
}
});
button.setOnTouchListener(newOnTouchListener(){
@Override
publicbooleanonTouch(View v,MotionEvent event){
System.out.println("Button:"+event.getAction());
returnfalse;
}
});
//my_ll.setOnClickListener(new OnClickListener() {
//
//@Override
//public void onClick(View v) {
//System.out.println("Linearlayout");
//}
//});
}
}
分析:my_ll不再向里面的Button和TextView传递了,自己处理,自己在my_ll.setOnTouchListener中返回了false,my_ll又不具备点击事件,当然就只能打印出LineraLayout::0了,如果我们给其设置了点击事件,那么当然会打印出down,up,click三者了。my_ll.setOnTouchListener中返回了true,自己也进行了处理,不过就只能打印出down,up了。
2:不拦截事件
分析:点击button,响应了事件,其可以点击,肯定会响应。点击TextView时候,其默认没有点击事件,只能打印down了,然后不响应,往回传递,my_ll去响应,my_ll又会通过View的dispatchTouchEvent去处理了。我们这里在my_ll.setOnTouchListener中返回了true的话,肯定会打印如下:TextView的down,MyLinearlayout的down,up了。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。