View 绘制机制 -- How Android Draws Views

来源:互联网 发布:foxpro数据库命令汇总 编辑:程序博客网 时间:2024/05/20 22:03

How Android Draws Views


When an Activity receives focus, it will be requested to draw its layout. The Android framework will handle the procedure for drawing, but the Activity must provide the root node of its layout hierarchy.

当Activity获得焦点就开始布局的绘制,但是它必须提供View树的根节点,Android框架则会着手处理绘制过程。

Drawing begins with the root node of the layout. It is requested to measure and draw the layout tree. Drawing is handled by walking the tree and rendering each View that intersects the invalid region. In turn, each View group is responsible for requesting each of its children to be drawn (with the draw() method) and each View is responsible for drawing itself. Because the tree is traversed in-order, this means that parents will be drawn before (i.e., behind) their children, with siblings drawn in the order they appear in the tree.

绘制过程从根节点开始,它要求测量和绘制整个布局树。绘制过程遍历View树,并渲染相交的失效区域。反过来,每个View Group对他各个孩子被绘制的要求作出响应,并且每个View自己作出绘制自己的响应(通过调用draw()方法)。由于View树是按顺序遍历的,这意味着父节点先于孩子被绘制完成,兄弟节点则依照树上出现的顺序。

Drawing the layout is a two pass process: a measure pass and a layout pass. The measuring pass is implemented in measure(int, int) and is a top-down traversal of the View tree. Each View pushes dimension specifications down the tree during the recursion. At the end of the measure pass, every View has stored its measurements. The second pass happens in layout(int, int, int, int) and is also top-down. During this pass each parent is responsible for positioning all of its children using the sizes computed in the measure pass.

布局的绘制经历两个过程:测量过程和布局过程。测量过程通过遍历View树由measure(int,int)完成。在这个递归遍历的过程中,每一个View将尺寸规格依次向下传递。在测量过程结束时,每一个View都保存了自己的尺寸。第二个过程也是自上而下的,由layout(int,int,int,int)触发。在这个过程中,每一个父节点用测量过程中保存的尺寸大小来布局所有的子节点。

The framework will not draw Views that are not in the invalid region, and also will take care of drawing the Views background for you.

You can force a View to draw, by callinginvalidate().

框架只会绘制失效区域(这里的意思是框架只会重绘需要绘制的区域,其他不需要绘制的区域属于有效区域,不需要重绘,这样增强了绘制效率),并且会注意为你绘制Views的背景。

你可以强制重回,调用invalidate()函数即可。

When a View's measure() method returns, its getMeasuredWidth() and getMeasuredHeight() values must be set, along with those for all of that View's descendants. A View's measured width and measured height values must respect the constraints imposed by the View's parents. This guarantees that at the end of the measure pass, all parents accept all of their children's measurements. A parent View may call measure() more than once on its children. For example, the parent may measure each child once with unspecified dimensions to find out how big they want to be, then call measure() on them again with actual numbers if the sum of all the children's unconstrained sizes is too big or too small (i.e., if the children don't agree among themselves as to how much space they each get, the parent will intervene and set the rules on the second pass).

当某个View的measure()方法返回时,它的getMeasuredWidth()getMeasuredHeight()方法获得的值必须设置,包括它的子孙View。View的测量width和height值必须遵循其父View。这保证在测量过程结束时,所有的父亲View都能接受孩子View的长度。父View调用measure()方法的次数可能比其孩子View调用的多一次。比如,父View会先以不确定的长度调用measure()一次以知道它们想要多大的尺寸,如果第一次测量的所有孩子View的尺寸之和大于或小于父View的尺寸,则会再一次调用measure()方法(如果每个孩子View不同意各自分配的大小,父View则会在第二个处理过程中设定规则)。

To initiate a layout, callrequestLayout(). This method is typically called by a View on itself when it believes that is can no longer fit within its current bounds.

初始化一个布局,调用requestLayout()。通常,当某个View认为当前的边界大小不再适应自身,它会调用这个函数。

The measure pass uses two classes to communicate dimensions. The ViewGroup.LayoutParams class is used by Views to tell their parents how they want to be measured and positioned. The base LayoutParams class just describes how big the View wants to be for both width and height. For each dimension, it can specify one of:

测量过程用两个类来交流尺寸。ViewGroup.LayoutParams告诉他们的父View想要怎么测量和怎么布局位置.基类LayoutParams描述了View自身需要的宽度和高度。每一个尺寸,可以用下面的属性来表示:

  • an exact number
  • FILL_PARENT, which means the View wants to be as big as its parent (minus padding)
  • WRAP_CONTENT, which means that the View wants to be just big enough to enclose its content (plus padding).

There are subclasses of LayoutParams for different subclasses of ViewGroup. For example, RelativeLayout has its own subclass of LayoutParams, which includes the ability to center child Views horizontally and vertically.

ViewGroup不同的子类都有响应的LayoutParams子类。

MeasureSpecs are used to push requirements down the tree from parent to child. A MeasureSpec can be in one of three modes:

测量规格有以下三种模式

  • UNSPECIFIED: This is used by a parent to determine the desired dimension of a child View. For example, a LinearLayout may call measure() on its child with the height set to UNSPECIFIED and a width of EXACTLY240 to find out how tall the child View wants to be given a width of 240 pixels.
  • EXACTLY: This is used by the parent to impose an exact size on the child. The child must use this size, and guarantee that all of its descendants will fit within this size.
  • AT_MOST: This is used by the parent to impose a maximum size on the child. The child must guarantee that it and all of its descendants will fit within this size.

原创粉丝点击