LinearLayout、RelativeLayout内部含有Button或者ImageButton点击事件失灵

一、我们先来了解一下View的事件传递

  • 分发——dispatchTouchEvent:方法返回值为true表示事件被当前视图消费掉;返回为super.dispatchTouchEvent表示继续分发该类事件。
  • 拦截——onInterceptTouchEvent:方法返回值为true表示拦截这个事件并交由自身的onTouchEvent方法进行消费;返回值为false表示不拦截,需要继续传递给子视图
    如果return super.onInterceptTouchEvent(ev),事件拦截分两种情况:
    1.如果该View(ViewGroup)存在子View且点击到了该子View,则不拦截,继续分发给子View处理,此相当于return false。
    2.如果该View(ViewGroup)没有子VIew或者有子View但是没有点中子View(此时的ViewGroup相当于普通的VIew),则交由该View的onTouchEvent相应,此时相当于return true。
    注意:一般的LinearLayout、RelativeLayout、FragmentLayout等ViewGroup默认不拦截,而SrcollView、ListView等ViewGroup则可能拦截,得看具体的情况。
    
  • 消费——onTouchEvent:方法返回值为true表示当前视图可以处理相应的事件,;返回值为false表示当前视图不处理这个事件,它会被传递给父视图onTouchEvent方法进行处理。如果return super.onTouchEvent(ev),事件分为两种情况:
    1.如果该View是clickable或者longclickable的,则会返回true,表示消费了该事件,与返回true一样;
    2.如果该View不是clickable或者longclickable的,则会返回false,表示不消费该事件,将会向上传递,与返回false一样。
    

二、为什么LinearLayout、RelativeLayout为什么会失效

由上面所说到的View的点击事件的传递,LinearLayout等布局属于是ViewGroup,而内部含有Button和ImageButton子View(如果点击到子View的),所以默认会不拦截,也就是会继续分发给子View,所以我们点击LinearLayout等布局的时候,点击事件会无效。解决办法就是将ViewGroup内部的子View的 clickable属性设置为false

android:clickable="false"

将子View失去焦点就可以恢复ViewGroup点击事件。

三、为什么LinearLayout内部含有TextView的时候,点击不会失效

View的onTouchEvent默认都会消耗事件(返回true),除非它是不可点击的(clickable 和 longClickable 同时为false)。View的longclickable属性默认是为false,clickable属性要分情况,因为Button的clickable属性默认的是true,而TextView的clickable属性默认是false的。

所以这就是,我们经常在LinearLayout等ViewGroup里面写了Button等子VIew的的时候(子VIew默认充满父布局),ViewGroup的点击事件会不能被拦截,因为会分发到子View。而ViewGroup内部是一个TextView的时候(也是充满父布局),点击VIewGroup的时候是会被拦截并消耗的。因为默认TextView的Clickable这个属性默认的是false

参考文章:https://jsonchao.github.io/2018/10/17/Android触摸事件传递机制/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值