【自定义View系列】导致View树重新遍历的时机

来源:互联网 发布:编程原本 pdf下载 编辑:程序博客网 时间:2024/06/03 14:29

  遍历View树就意味着整个View需要重新对其包含的子视图分配大小并重绘。导致重新遍历的原因主要有三个:
1. 视图本身内部状态变化引起重绘。
2. View树内部添加或者删除了View。
3. View本身的大小及可见性发生变化。

状态的分类

这里写图片描述

  在View视图中定义了多种和界面效果相关的状态。不同的状态一般会显示不同的界面效果,有多种操作会引起这些状态的改变。Android中应用程序是按照消息机制执行的,每次处理一个消息,如果该消息引起状态改变,则代码中仅仅做一些状态标识,然后发送一个异步消息,而不是立即重绘。然后在下一次消息处理中,根据保存的状态数据,绘制不同的界面效果。

  视图中和显示效果相关的状态一共有15种 —— android.graphics.drawable.StateListDrawable类中定义。

selected和focused的区别

  一个窗口中只能有一个视图获得焦点,当用户按键时,获取焦点的视图会变得高亮起来,而一个窗口可以有多个视图处于selected状态。
  按键消息最终会传递到focused视图中,而不是selected视图中。
当某个视图处于pressed状态时,如果将其selected状态设为false,那么该视图的pressed状态就会被清空。
focused状态一般是由按键操作引起的,pressed状态是由触摸消息引起的,selected则完全是由应用程序主动调用 setSlected()进行控制。
当视图重绘时,会根据当前不同的状态选择不同的背景图(selector来定义背景时)。

导致View树重新遍历的总体诱因

导致视图大小发生变化 —— invalidate()
导致ViewGroup重新为子视图分配位置 —— requestLayout()
视图显示情况发生变化需要重绘 —— requestFocus()
这三个函数最终都会调用到ViewRoot中的 schueduleTraversals()函数,该函数会发起一个异步消息,消息处理中调用 performTraversals()开始对整个View进行重新遍历。

invalidate()

能导致调用invalidate()函数的包括三种情况:
1. 调用setVisibility():当应用程序改变视图显示属性时。
2. setSelected():当改变视图Selected状态时。
3. setEnable():当改变视图Enable状态时。

requestLayout()

导致调用requestLayout()函数的情况包括两种:
1. setVisibility(),当应用程序改变视图显示属性时,由于显示或者不显示将影响其他同级视图的位置。
2. 应用程序直接或间接调用到该函数,间接调用是指应用程序调用了View类的其他函数,从而简介调用到requestLayout()。

requestFocus()

一般由程序直接调用,简介调用是指当用户按”上/下”、”左/右”键时,相关的处理逻辑会间接的调用到该函数。

0 0
原创粉丝点击