android自定义控件事件的传递

自定义关键事件的传递(一)
      在自定义空间中事件的传递十分重要,为了记录和巩固知识特此记录, 由于水平有限,不对的地方希望可以给小弟指正。
      不废话,先上张图

上面这张图描述的是事件的传递,当我们点击button的时候事件上事件的传递是先走的RelativeLayout的触摸事件,之后传递给Button,在Button没有消耗的情况下,还会传递给上一层。
   下面上代码验证一下:布局就是一个自定义的相对布局relative里面放置一个自定义的Button,并重写里面的 代码如下:
@SuppressLint("AppCompatCustomView")
public class MyButton extends Button {
    private static final String TAG = "lang";
    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.i(TAG,"Button dispatchTouchEvent");
        return super.dispatchTouchEvent(event);
    }
}

          因为代码重复,直上一个的代码,运行之后我们查看打印的结果。

这里的dispatchTouchEvent方法就是做事件分发用的,好的我们先岔开话题,讨论一下,View的OnTouch事件和OnClick事件的关系,代码的写法布局上是一样的,不多说先上代码:
  Button button = (Button) findViewById(R.id.btn);
 button.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                Log.i(TAG,"Button onTouch"+motionEvent.getAction());
                return true;
            }
        });

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.i(TAG,"Button OnClick");
            }
        });




  
  
            运行打印看效果:
      首先运行的事OnTouch事件,之后才走的OnClick事件,当我们OnTouch返回true的时候,运行看效果:
我们发现OnClick事件没有响应,原因是没有接收到UP事件。所以我们可以得到以下的结论:
1.控件的Listener事件触发的顺序是先onTouch,再onClick。
2.控件的onTouch返回true,将会onClick事件没有了---阻止了事件的传递。
 返回false,才会传递onClick事件(才会传递up事件)
下面我们来讨论,View本身的 onTouch事件和 Listener事件还有 dispatchTouchEvent事件之间的关系:

            先贯穿以下顺序,不多说先上代码首先是设置一个touch监听,之后再View中:
@SuppressLint("AppCompatCustomView")
public class MyButton extends Button {
    private static final String TAG = "lang";
    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.i(TAG,"Button dispatchTouchEvent");
        return super.dispatchTouchEvent(event);
//        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG,"Button onTouchEvent");
        return super.onTouchEvent(event);
    }
}

打印验证事件传递的顺序:
这个是走的顺序,当我们在

这里只返回true的时候,我们运行的效果是
也就是是说事件会在这里终止,但是,当我们这样的时候:
效果:
所以super.dispatchTouchEvent是实际的分发代码,同理,我们的OnTouch也是如此,这里我们就不验证了。
但是我们在 Listener事件里面返回true的时候呢?
当:
运行的效果是这样的:
所以我们可以得到这样的结论:

1.如果onTouchListener的onTouch方法返回了true,那么view里面的onTouchEvent就不会被调用了。
顺序dispatchTouchEvent-->onTouchListener---return false-->onTouchEvent

2.如果view为disenable,则:onTouchListener里面不会执行,但是会执行onTouchEvent(event)方法

3.onTouchEvent方法中的ACTION_UP分支中触发onclick事件监听
onTouchListener-->onTouch方法返回true,消耗次事件。down,但是up事件是无法到达onClickListener.
onTouchListener-->onTouch方法返回false,不会消耗此事件

后两条结论是通过分析源码所得来的:这里就不分析源码了,可以自己去验证,希望对小伙伴们有帮助。有错的地方可以留言指正。谢谢







  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值