Android面试-9 View事件体系

View的事件分发

public static dispatchTouchEvent(MotionEvent e){
    boolean consume = false;
    if(onInterceptTouchEvent(e)) {
        consume = onTouchEvent(e);
    } else {
        consume = child.dispatchTouchEvent(e);    
    }
    return consume;
}
  • dispatchTouchEvent:是否消耗该事件。由当前View的onTouchEvent和下级View的dispatchTouchEvent共同决定
  • onInterceptTouchEvent:是否拦截该事件。外部拦截法便是通过重写父容器的onInterceptTouchEvent,返回true拦截事件。被拦截后,同一个事件序列中这个View的onInterceptTouchEvent不会再被调用
  • onTouchEvent:处理事件并返回是否消耗。处理事件优先级onTouch > onTouchEvent > onClick。若View不消耗ACTION_DOWN事件,即返回false,则同一事件序列的其他事件如UP,MOVE等重新交给父容器的onTouchEvent处理。

View的滑动

  • 使用ScrollerTo/by:只能改变View内容位置,无法改变View在布局中的位置
  • 使用动画:View动画只是操作影像,属性动画则可以真正改变布局位置属性,可以应对需要处理交互的场景。
  • 改变LayoutParams:比如设置marginLeft等,实现较麻烦但也可以满足需要交互的场景。

View的弹性滑动

  • Scroller:View在onDraw方法中调用computeScroller(我们在里面实现弹性滑动代码),它会通过Scroller对象获取当前的ScrollX、ScrollY,通过时间流逝计算新的滑动距离,和是否滑动停止,若还未停止,在通过scrollTo实现滑动,调用postInvalidate进行第二次重绘,如此反复。
  • 使用动画:属性动画ValueAnimator
  • 使用延时策略:通过Scrollto+Handler,或View的postDelayed

滑动冲突解决

  • 外部拦截法:重写父容器的onInterceptTouchEvent方法,写入拦截逻辑,注意ACTION_DOWN和ACTION_UP都要返回false,拦截应该在ACTION_MOVE中设置。
  • 内部拦截法:子容器需要事件则消耗,不交给父容器处理。步骤如下:
首先,重写子元素的dispatchTouchEvent
ACTION_DOWN: parent.requestDisallowInterceptionTouchEvent(true) //不拦截ACTION_DOWN事件
ACTION_MOVE:if(有拦截父容器业务需求) {
parent.requestDisallowInterceptionTouchEvent(false)
}
return super.dispatchTouchEvent(e);
其次,修改父容器的onInterceptTouchEvent
ACTION_DOWN: return false; //确保ACTION_DOWN不拦截,其他的事件则都要拦截
else return true;



阅读更多
个人分类: Android面试
所属专栏: Android面试
上一篇Android面试-1 Activity生命周期和启动模式
下一篇Android面试-10 View工作原理
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭