Created
December 12, 2013 03:25
-
-
Save ixiyang/7922758 to your computer and use it in GitHub Desktop.
android view 绘制流程
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
关于view的绘制流程 | |
View | |
ViewParent(interface) | |
ViewGroup(extends View implements ViewParent) | |
ViewRoot(implements ViewParent) | |
Being a root parent of all views in the activity, the ViewRootschedules traversals of all the views in | |
order to first lay them out at the right place with the right size; this is called the layout phase. The | |
ViewRoot then traverses the view hierarchy to draw them; this phase is called the drawing phase. | |
We will talk about each of these phases now.(ViewRoot是每个activity视图层级的最顶层。负责整个视图的layout和draw两个过程) | |
Layout Phase: Measurement and Layout | |
布局阶段:确定视图层级中视图的大小和位置。 | |
Measure pass | |
The measure pass is implemented by the measure( ) function of the Viewclass.The signature of this function is | |
public final void measure(int widthMeasureSpec, int heightMeasureSpec) | |
Make a note of this method’s signature. This signature will help you to easily locate this method | |
measure( ) in the source code of the large View.javasource file. This method, measure( ), does some | |
housekeeping and calls the onMeasure( ) of the derived views. The derived views need to set their | |
dimensions by calling setMeasuredDimension(). These measured dimensions set on each view are | |
then subsequently used in the layout pass. In this context, your primary override is View.onMeasure(). | |
Keep in mind that there is a default implementation for onMeasure(). The default implementation of | |
onMeasure( ) decides the size of your view based on suggestions from the layout files, including an | |
exact size passed in. We will cover this later in the chapter. | |
Although it is the onMeasure( ) that you care about when you are a creating custom view like the | |
CircleView, there are times when measure( ) is important as well. If the inherited custom view is a | |
collection of other views, as in a ViewGroup, then you need to call measure( ) on child views in your | |
onMeasure( ) method. The signature of measure( ) earlier clearly supports the idea that you can’t | |
override it by being final, but you are expected to call it by being public. We will cover the measure( ) | |
method arguments widthMeasureSpecand heightMeasureSpecwhen we work with onMeasure()later | |
in this chapter. | |
Layout pass | |
After the measure pass, each view knows its dimensions. The control then passes to the layout pass. | |
This layout pass is implemented in the layout( ) method, whose signature in the base Viewclass is: | |
public void layout(int left, int top, int right, int bottom) | |
Much like the measure( ) method, the layout( ) method carries out an internal protocol for the base | |
Viewand result in calling the overridden methods in Listing 1-1, in that order. | |
Listing 1-1. Overridden Methods Called by a View’s Layout( ) Method | |
protected void onSizeChanged(int w, int h, int oldw, int oldh); | |
protected void onLayout(boolean changed, int left, int top, int right, int bottom) | |
The layout pass, implemented in layout( ), will take the dimensions measured by the measure | |
pass into account and give out the starting position for each view and the dimension each view | |
needs to use. The base layout( ) method actually sets these dimensions on the view on which it is | |
called. It then calls the onSizeChanged( ) if there is actually a change in size or position. The default | |
implementation of onSizeChanged( ) exists in the Viewclass but it is a no-op. | |
After calling the onSizeChanged( ) method, the layout( ) method calls the onLayout( ) to allow | |
for something like a view group to call layout( ) on its children. The default implementation for | |
onLayout( ) exists but it is a no-op. To apply this to our CircleView, we don’t need to do anything in | |
the onLayout( ) because our position and dimensions are already fixed, and we have no children to | |
advise their layouts by calling their layout( ) method. | |
Once both of the passes of the layout phase are completed, the traversal initiated by the view root | |
will move to the drawing phase. | |
Drawing Phase: Mechanics of onDraw | |
The draw traversal is implemented in the View's draw( ) method. The protocol implemented by this | |
method is: | |
Draw the background | |
Draw view's content by delegating to onDraw() | |
Draw children by delegating to dispatchDraw() | |
Draw decorations such as scroll bars | |
Because the draw traversal happens after the layout traversal, you already know the position and the | |
size of your views. If your view like the CircleViewdoesn’t have children, you don’t care much about | |
dispatchDraw( ). The default implementation for this method in the base Viewclass exists but is empty. | |
You could ask: If my custom view has children, why am I not choosing to draw them in onDraw? | |
Perhaps because, in a framework, the base class View'sfixed protocol of draw( ) may choose | |
to do something between your onDraw( ) and your children’s onDraw( ). So, it is suggested to the | |
programmer, by dispatchDraw( ) of the View, that the View’s drawing is complete and the derived | |
implementation could choose whatever is needed. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment