Android之View总结篇

1. 讲下View的绘制流程?

  1. View 的工作流程主要是指 measure、layout、draw 这三大流程,即测量、布局和绘制,其中 measure 确定 View 的 测量宽/高,layout 确定 View 的 最终宽/高和四个顶点的位置,而 draw 则将 View 绘制到屏幕上
  2. View的绘制过程遵循如下几步:
    1. 绘制背景 background.draw(canvas)
    2. 绘制自己(onDraw)
    3. 绘制 children(dispatchDraw)
    4. 绘制装饰(onDrawScollBars)
      在这里插入图片描述

2. MotionEvent是什么?包含几种事件?什么条件下会产生?

  1. MotionEvent是手指接触屏幕后所产生的一系列事件。典型的事件类型有如下:

    1. ACTION_DOWN:手指刚接触屏幕;

    2. ACTION_MOVE:手指在屏幕上移动;

    3. ACTION_UP:手指从屏幕上松开的一瞬间;

    4. ACTION_CANCELL:手指保持按下操作,并从当前控件转移到外层控件时触发;

  2. 正常情况下,一次手指触摸屏幕的行为会触发一系列点击事件,考虑如下几种情况:

    1. 点击屏幕后松开,事件序列:DOWN→UP

    2. 点击屏幕滑动一会再松开,事件序列为DOWN→MOVE→…→MOVE→UP


3. 描述一下View事件传递分发机制?

  1. View 事件分发本质就是对 MotionEvent 事件分发的过程。即当一个 MotionEvent 发生后,系统将这个点击事件传递到一个具体的 View上;

  2. 点击事件的传递顺序:Activity(Window)→ViewGroup→ View

  3. 事件分发过程由三个方法共同完成:

    1. dispatchTouchEvent:用来进行事件的分发。如果事件能够传递给当前 View,那么此方法一定会被调用,返回结果受当前 View 的 onTouchEvent 和下级 View 的 dispatchTouchEvent 方法的影响,表示是否消耗当前事件;

    2. onInterceptTouchEvent:在上述方法内部调用,对事件进行拦截。该方法只在 ViewGroup 中有,View(不包含 ViewGroup)是没有的。一旦拦截,则执行 ViewGroup 的 onTouchEvent,在 ViewGroup 中处理事件,而不接着分发给 View。且只调用一次,返回结果表示是否拦截当前事件;

    3. onTouchEvent: 在 dispatchTouchEvent 方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件;


4. 如何解决View的事件冲突 ? 举个开发中遇到的例子 ?

  1. 常见开发中事件冲突的有ScrollView与RecyclerView的滑动冲突、RecyclerView内嵌同时滑动同一方向

  2. 滑动冲突的处理规则:

    1. 对于由于外部滑动和内部滑动方向不一致导致的滑动冲突,可以根据滑动的方向判断谁来拦截事件。
    2. 对于由于外部滑动方向和内部滑动方向一致导致的滑动冲突,可以根据业务需求,规定何时让外部View拦截事件,何时由内部View拦截事件。
    3. 对于上面两种情况的嵌套,相对复杂,可同样根据需求在业务上找到突破点。
  3. 滑动冲突的实现方法:

    1. 外部拦截法:指点击事件都先经过父容器的拦截处理,如果父容器需要此事件就拦截,否则就不拦截。具体方法:需要重写父容器的onInterceptTouchEvent方法,在内部做出相应的拦截。

    2. 内部拦截法:指父容器不拦截任何事件,而将所有的事件都传递给子容器,如果子容器需要此事件就直接消耗,否则就交由父容器进行处理。具体方法:需要配合requestDisallowInterceptTouchEvent方法。


5. scrollTo()和scollBy()的区别?

  1. scollBy 内部调用了 scrollTo,它是 基于当前位置的相对滑动;而 scrollTo 是绝对滑动,因此如果使用相同输入参数多次调用scrollTo 方法,由于 View 的初始位置是不变的,所以只会出现一次 View 滚动的效果;
  2. 两者都只能对 View 内容的滑动,而非使 View 本身滑动。可以使用 Scroller 有过度滑动的效果;

6. Scroller是怎么实现View的弹性滑动?

  1. 在 MotionEvent.ACTION_UP 事件触发时调用 startScroll() 方法,该方法并没有进行实际的滑动操作,而是记录滑动相关量(滑动距离、滑动时间);
  2. 接着调用 invalidate / postInvalidate() 方法,请求 View 重绘,导致 View.draw 方法被执行;
  3. 当 View 重绘后会在 draw 方法中调用 computeScroll 方法,而 computeScroll 又会去向 Scroller 获取当前的 scrollX 和 scrollY;然后通过 scrollTo 方法实现滑动;接着又调用 postInvalidate 方法来进行第二次重绘,和之前流程一样,如此反复导致 View 不断进行小幅度的滑动,而多次的小幅度滑动就组成了弹性滑动,直到整个滑动过成结束;
    在这里插入图片描述

7. invalidate()和postInvalidate()的区别 ?

  1. invalidate() 与 postInvalidate() 都用于刷新 View,主要区别是 invalidate() 在主线程中调用,若在子线程中使用需要配合 handler;而 postInvalidate() 可在子线程中直接调用。

8. SurfaceView和View的区别?

  1. View 需要在 UI 线程对画面进行刷新,而 SurfaceView 可在子线程进行页面的刷新;

  2. View 适用于主动更新的情况,而 SurfaceView 适用于被动更新,如频繁刷新,这是因为如果使用 View 频繁刷新会阻塞主线程,导致界面卡顿;

  3. SurfaceView 在底层已实现双缓冲机制,而 View 没有,因此 SurfaceView 更适用于需要频繁刷新、刷新时数据处理量很大的页面(如视频播放界面);


9. 自定义View如何考虑机型适配 ?

  1. 合理使用 warp_content,match_parent;

  2. 尽可能的是使用 RelativeLayout;

  3. 针对不同的机型,使用不同的布局文件放在对应的目录下,android 会自动匹配。

  4. 尽量使用点 9 图片;

  5. 使用与密度无关的像素单位dp,sp;

  6. 引入 android 的百分比布局;

  7. 切图的时候切大分辨率的图,应用到布局当中。在小分辨率的手机上也会有很好的显示效果;


声明:本文整理自网络,如有侵权请联系我。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liusaisaiV1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值