Android触摸屏事件派发机制View的一些事一些情


1普通的控件,buttom,Textview。。。。


    private LinearLayout mLayout;
    private Button mButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLayout = (LinearLayout) this.findViewById(R.id.mylayout);
        mButton = (Button) this.findViewById(R.id.my_btn);
        mLayout.setOnTouchListener(this);
        mButton.setOnTouchListener(this);
        mLayout.setOnClickListener(this);
        mButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        Log.i("lyf", "OnClickListener--onClick--" + v);
    }

     //public static final int ACTION_DOWN = 0;
     //public static final int ACTION_UP  = 1;
     //public static final int ACTION_MOVE = 2;
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.i("lyf", "OnTouchListener--onTouch-- action=" 
        + event.getAction() + " --" + v);
        return false;
    }

情景1、可以看到我们onTouch方法返回false,不消费该事件,往下层传递。

I/lyf: OnTouchListener--onTouch-- action=0 --android.widget.Button 
I/lyf: OnTouchListener--onTouch-- action=2 --android.widget.Button
I/lyf: OnTouchListener--onTouch-- action=2 --android.widget.Button
I/lyf: OnTouchListener--onTouch-- action=2 --android.widget.Button
I/lyf: OnTouchListener--onTouch-- action=2 --android.widget.Button 
I/lyf: OnTouchListener--onTouch-- action=1 --android.widget.Button
I/lyf: OnClickListener--onClick--android.widget.Button

情景2、在onTouch方法返回true,消费该事件,不往下层传递了。onClick方法自然而然也没有接收到信息了,至于为什么不传递到onClick方法里面,我们来看看源码就知道了:

       if (!mHasPerformedLongPress) {
     // This is a tap, so remove the longpress check
             removeLongPressCallback();
     // Only perform take click actions if we were in the pressed state
                   if (!focusTaken) {
      // Use a Runnable and post this rather than calling
       // performClick directly. This lets other visual state
       // of the view update before click actions start.
              *if (mPerformClick == null) {
                    mPerformClick = new PerformClick();
                    }
                     if (!post(mPerformClick)) {
                             performClick();
                      }
             }*
        }

performClick()这个方法就是关于点击事件的,而这个方法是在onTouchEvent方法里面,而    onTouch方法又优先于onTouchEvent方法,那再看看为什么onTouch优先于onTouchEvent吧!

        public boolean dispatchTouchEvent(MotionEvent event){
        ... ...
        if(onFilterTouchEventForSecurity(event)){
          ListenerInfo li = mListenerInfo;

         if(li != null && li.mOnTouchListener != null 
         && (mViewFlags & ENABLED_MASK) == ENABLED
          && li.mOnTouchListener.onTouch(this, event)) {
                return true;
            }

            if(onTouchEvent(event)){
                return true;
            }
        }
        ... ...
        return false;
    }

li.mOnTouchListener.onTouch()这个方法就在分发事件中调用, 为什么onTouch方法执行优先于onTouchEvent,跟踪源码:
很明显可以看到,事件的传递,会优先掉用mOnTouchListener.onTouch(this, event)这个方法,
然后才能轮到onTouchEvent(event)获取事件,顺序如此,有什么可说。既然说到这里,我们也应该想起了onClick和onLongPressClic都是对onTouchEvent(event)的依赖,
如果在setOnTouchListener.onTouch()的时候返回true,那么onTouchEvent方法不会被调用。
同样,内置诸如click事件的实现等等都基于onTouchEvent,假如onTouch返回true,这些事件将不会被触发。因为有3个判断满足的情况下,就不会进入onTouchEvent了,只有不满足的情况下才会进入。
I/lyf: OnTouchListener--onTouch-- action=0 --android.widget.Button
I/lyf: OnTouchListener--onTouch-- action=2 --android.widget.Button
I/lyf: OnTouchListener--onTouch-- action=2 --android.widget.Button
I/lyf: OnTouchListener--onTouch-- action=1 --android.widget.Button

最后,在这里总结一点,上面2个列子,onTouch-onClick,如果消费了,点击就没有效果了。

2自定义一个控件来实现dispatchTouchEvent(触摸事件分发)、onTouchEvent(触摸事件)、在Activity中实现onTouch方法和onClick方法。在这里我只是记录一下事件分发的日志,以方便日后不用每次的测试一下。

情景1;

public class TestButton extends Button {
    ...........................
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.i("lyf", "dispatchTouchEvent-- action=" + event.getAction());
        return super.dispatchTouchEvent(event);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i("lyf", "onTouchEvent-- action="+event.getAction());
        return super.onTouchEvent(event);
    }
}

public class ListenerActivity extends Activity 
implements View.OnTouchListener, View.OnClickListener {
        ................................
    @Override
    public boolean onTouch(View v, MotionEvent event) {
     Log.i("lyf", "OnTouchListener--onTouch-- action=" 
     + event.getAction() + " --" + v);
       return false;
    }

    @Override
    public void onClick(View v) {
        Log.i("lyf", "OnClickListener--onClick--" + v);
    }

}

结果:

I/lyf: dispatchTouchEvent– action=0
I/lyf: onTouch– action=0
I/lyf: onTouchEvent– action=0
I/lyf: dispatchTouchEvent– action=2
I/lyf: onTouch– action=2
I/lyf: onTouchEvent– action=2
I/lyf: dispatchTouchEvent– action=1
I/lyf: onTouch– action=1
I/lyf: onTouchEvent– action=1
I/lyf: onClick–com.example.xiaolin.mytochuview.TestButton

可以看到事件分发由上车到下车,中途没有乘客,哈哈,不知道这样说对不对了!,写到这里就不写了,大家可以自行修改值,来看看结果,中途可以上车,也可以下车,。。

最后,重点,返回值,
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
   Log.i("lyf", "dispatchTouchEvent-- action=" + event.getAction());
   return true;
}
再看一下结果:

com.example.xiaolin.mytochuview I/lyf: dispatchTouchEvent– action=0
com.example.xiaolin.mytochuview I/lyf: dispatchTouchEvent– action=2
com.example.xiaolin.mytochuview I/lyf: dispatchTouchEvent– action=2
com.example.xiaolin.mytochuview I/lyf: dispatchTouchEvent– action=2
com.example.xiaolin.mytochuview I/lyf: dispatchTouchEvent– action=2
com.example.xiaolin.mytochuview I/lyf: dispatchTouchEvent– action=1
“`
返回值为true,不再往下传递了(消费了该事件),false(没有消费该事件)!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值