Android View事件传面试相关

View 事件分发(csdn)

  • 传递图示

  • 事件拦截的应用场景
  • 面试题
    • 为什么要有事件传递机制
      • 因为android的view 是树形结构,当点击事件发生的时候 要经过好几层的View ,若是没有事件传递机制 ,就没办法确定这个事件给谁处理了,所以事件传递机制就是为了处理这个问题而出现的
    • android布局加载的过程
      • 用户执行Activity的setContentView方法,内部是PhoneWindow的setContentView方法,在PhoneWindow中完成DecorView的创建,
      • PhoneWindow是window的实现类.
      • DecorView是Activity的根View,也是PhotoWindow的内部类,并且继承了Framlayout.
      • DecorView将屏幕分为2个部分:titleView和contentView,我们平常加载的布局就是ContentView.
    • android 事件传递的三个重要方法

      • viewgroup 拥有这三个方法 acitivity和view没有拦截方法,

    • 事件分发的流程
      • Activity——>PhoneWindow——>DecorView——>ViewGroup——>...——>View

    • onTouchListener,onTouchEvent和onClick的优先级别
      • onTouchListener—–>onTouchEvent—>onclick
      • onTouchListener >>> onTouchEvent >>> setOnLongClickListener >>> OnClickListerner
      • 总结
        • onTouch的优先级高于onClick
        • 控件被点击时,onTouch返回false—>dispatchTouchEvent方法返回false—>执行onTouchEvent—>在performClick方法里回调onClick
        • onTouch返回true—>dispatchTouchEvent方法返回true—>不执行onTouchEvent,显然onClick方法也不会被调用
        • 参考https://juejin.im/entry/58df5b33570c35005798493c
      • 面试口述
        • onTouchListener 的优先级要高于onTouchEvent ,若onTouchListener返回的是true onTouchEvent 就不执行了
    • View中为什么没有onInterceptTouchEvent事件拦截方法?
      • View最为事件传递的最末端,要么消费掉事件,要么不处理进行回传,根本没必要进行事件拦截
    • 用伪代码表示ViewGroup的事件分发过程并解释?

      • 对于一个ViewGroup来说,点击事件产生后,首先会传递给它,这时她的dispatchTouchEvent会被调用,如果这个ViewGroup的onInterceptTouchEvent,方法返回true表示它要拦截当前事件,接着事件就会交给这个ViewGroup处理,即它的onTouchEvent就会被调用;如果这个这个ViewGroup的onInterceptTouchEvent,方法返回false就表示它不拦截当前事件,这时事件就会传递给子元素,接着子元素的dispatchTouchEvent方法就会被调用,如此反复直到事件最终被处理。
    • 常见的注意问题
      • 如果事件一直没有被消费,最后会传给Activity,如果Activity也不需要就被抛弃。
      • view事件执行顺序dispatchTouchEvent-> setOnTouchListener的onTouch->onTouchEvent,如果setOnTouchListener返回ture,后续事件onTouchEvent不在执行
      • onClick是在onTouchEvent(event)方法中的,所以onTouch优先于onClick执行
      • 如果重写dispatchTouchEvent方法,dispatchTouchEvent无论返回true还是false,事件都不再进行分发, 只有当其返回super.dispatchTouchEvent(ev),才表明其具有向下层分发的愿望。
    • setOnLongClickListener的onLongClick的返回值表示什么?
      • 返回false,长按的话会同时执行onLongClick和onClick;如果setOnLongClickListener返回true,表示事件被消耗,不会继续传递,只执行longClick;
    • requestDisallowInterceptTouchEvent 可以在子元素中干扰父元素的事件分发吗?如果可以,是全部都可以干扰吗?
      • 答:肯定可以,但是down事件干扰不了。
  • 简述事件传递的流程
    • 事件都是从Activity.dispatchTouchEvent()开始传递
    • 一个事件发生后,首先传递给Activity,然后一层一层往下传,从上往下调用dispatchTouchEvent方法传递事件:
    • activity --> ~~ --> ViewGroup --> View
    • 如果事件传递给最下层的View还没有被消费,就会按照反方向回传给Activity,从下往上调用onTouchEvent方法,最后会到Activity的onTouchEvent()函数,如果Activity也没有消费处理事件,这个事件就会被抛弃:
    • dispatchTouchEvent方法用于事件的分发,Android中所有的事件都必须经过这个方法的分发,然后决定是自身消费当前事件还是继续往下分发给子控件处理。返回true表示不继续分发,事件没有被消费。返回false则继续往下分发,如果是ViewGroup则分发给onInterceptTouchEvent进行判断是否拦截该事件。
    • onTouchEvent方法用于事件的处理,返回true表示消费处理当前事件,返回false则不处理,交给子控件进行继续分发。
    • onInterceptTouchEvent是ViewGroup中才有的方法,View中没有,它的作用是负责事件的拦截,返回true的时候表示拦截当前事件,不继续往下分发,交给自身的onTouchEvent进行处理。返回false则不拦截,继续往下传。这是ViewGroup特有的方法,因为ViewGroup中可能还有子View,而在Android中View中是不能再包含子View的
    • 上层View既可以直接拦截该事件,自己处理,也可以先询问(分发给)子View,如果子View需要就交给子View处理,如果子View不需要还能继续交给上层View处理。既保证了事件的有序性,又非常的灵活。
    • 事件由父View传递给子View,ViewGroup可以通过onInterceptTouchEvent()方法对事件拦截,停止其向子view传递
    • 如果View没有对ACTION_DOWN进行消费,之后的其他事件不会传递过来,也就是说ACTION_DOWN必须返回true,之后的事件才会传递进来
  • 应用场景
    • 常见的滑动冲突
      • 外部滑动方向和内部滑动方向不一致的场景
        • ViewPager和Fragment配合使用组成的页面滑动效果。这种冲突的解决方式,一般都是根据水平滑动还是竖直滑动(滑动的距离差)来判断到底是由谁来拦截事件
      • 外部滑动方向和内部滑动方向一致的场景
        • 内外两层同时能上下滑动或者能同时左右滑动。这种一般都是根据业务来进行区分。例如 ScrollView 和ListView 滑动的场景
    • 滑动事件冲突解决方案
      • 内部拦截法
      • 外部拦截法
  • 基于上述总结写了一个事件传递的例子
  • 面试视角
  • 参考
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值