Android的事件响应机制

1:View的事件响应机制(控件:如TextView,ImageView,Button等)

     

     在执行onTouchListener方法时候,(view这里代表为控件)

                 view.setOnTouchListener (new OnTouchListener() {

                

                 @Override

                 public boolean onTouch( View v, MotionEvent event) {

                      return false ;

                 }

            });

    事件分发的时候会执行publicboolean dispatchTouchEvent(MotionEvent event)

  a:先进行if判断

         if (li != null && li .mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED

                    && li .mOnTouchListener .onTouch (this, event)) {

                return true ;

            }

      return onTouchEvent(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

     public boolean onInterceptTouchEvent( MotionEvent ev) {

            return true ;

     }

   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:拦截事件


自定义控件

public class MyLinearLayout extends LinearLayout {


     public MyLinearLayout (Context context , AttributeSet attrs ) {

            super(context , attrs );

     }

     @Override

     public boolean onInterceptTouchEvent( MotionEvent ev) {

            return true ;

     }

}

MainActivity

public class MainActivity extends Activity {


     private LinearLayout my_ll;

     private Button button;

     private TextView textView;

     @Override

     protected void onCreate( 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(new OnTouchListener() {

                

                 @Override

                 public boolean onTouch( View v, MotionEvent event) {

                     System .out.println( "Linearlayout:"+event .getAction ());

                      return true ;

                 }

            });

           

            textView. setOnTouchListener(new OnTouchListener() {

                

                 @Override

                 public boolean onTouch( View v, MotionEvent event) {

                     System .out.println( "TextView:"+event .getAction ());

                      return false ;

                 }

            });

           

            button. setOnTouchListener(new OnTouchListener() {

                

                 @Override

                 public boolean onTouch( View v, MotionEvent event) {

                     System .out.println( "Button:"+event .getAction ());

                      return false ;

                 }

            });

           

//         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了。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。