Android View System parsing (bottom)

Source: Internet
Author: User

Reprint Please specify source: http://blog.csdn.net/singwhatiwanna/article/details/38426471 (from Singwhatiwanna's CSDN blog)

Android View System Parsing series:

Android View system resolution (top)

Introduction to view basics, view sliding, elastic sliding, sliding conflict resolution, event distribution, and more

Android View System parsing (bottom)

Introduces the framework layer principle of view, the Measure/layout/draw three processes of view and some advanced techniques

This main introduction of the second half, the outline is as follows

The drawing process of view

Measure/layout/draw Work Flow

Identify Measurespec and make the right Measurespec

Get the View's wide height before rendering

Construct a special View

Custom View

Custom View Categories

customizing View Notes


the drawing process of a view first knowledge of Viewroot

Viewroot
Corresponds to the Viewrootimpl class, which is the link between WindowManager and Decorview.
Activitythread when the activity object is created, the Decorview is added to the window to complete the Viewrootimpl creation and Decorview connection.
root = new Viewrootimpl (View.getcontext (), display);
Root.setview (view, Wparams, Panelparentview);
The drawing process for view starts with the Viewroot performtraversals, which is the code flow:
Performmeasure, Measure, onmeasure
PerformLayout, Layout, onlayout
Performdraw, Draw, OnDraw

composition of the activity interface

From the Decorview as a top view, generally it has the upper and lower parts (the case will be related to the API version and theme), above is the title, the following is the content, In the activity we call the view set by Setcontentview is actually added to the content, and how to get content, you can: ViewGroup group = Findviewbyid ( r.android.id.content), how to get the view we set, can be like this: Group.getchildat (0). At the same time, through the source code we can know, Decorview is actually a framelayout. One point to note here is that most of the events in the view layer are passed from Decorview to our view.


Measurespec

Measurespec
Encapsulates the parent container's restrictions on the layout of the view, providing a wide range of information (Specmode, specsize), specsize refers to the reference size under a certain specmode, where Specmode has the following three kinds:
UNSPECIFIED
Parent container does not have any restrictions on view, how big
Exactly
The parent container has detected the size required for the view
At_most
The parent container specifies a size that cannot be greater than the size of the view
The meaning of Measurespecs
By packaging Specmode and specsize into an int value to avoid excessive object memory allocation, it provides a package/Jie Baofang method for ease of operation

the realization of Measurespec

Measurespec

Represents a 32-bit int value
High 2-bit stands for specmode, low 30-bit for specsize

Let's take a look at the definitions of some constants inside Measurespec, and it's not difficult to understand how MEASURESPEC works with the code below.

private static final int mode_shift = 30;private static final int mode_mask = 0x3 << mode_shift;public static final int UNSPECIFIED = 0 << mode_shift;public static final int exactly = 1 << mode_shift;public static final int at _most = 2 << mode_shift;public static int makemeasurespec (int size, int MODE) {if (Susebrokenmakemeasurespec) {retur n size + mode;} else {return (size & ~mode_mask) | (Mode & Mode_mask);}} public static int GetMode (int measurespec) {return (Measurespec & Mode_mask);} public static int GetSize (int measurespec) {return (Measurespec & ~mode_mask);}
Measurespec and LayoutparamsFor Decorview, its measurespec is determined by the size of the window and its own layoutparams.
For application-layer View, its measurespec is determined by the measurespec of the parent container and its own layoutparams.
Measurespec once determined, the onmeasure can determine its own width and height
Measurespec-decorview

The measurespec of the top container Decorview is analyzed here.

Childwidthmeasurespec = Getrootmeasurespec (basesize, lp.width);
Childheightmeasurespec = Getrootmeasurespec (Desiredwindowheight, lp.height);
Performmeasure (Childwidthmeasurespec, Childheightmeasurespec);

The above code describes the process of Decorview's measurespec, and in order to understand it more clearly, we continue to see

private static int Getrootmeasurespec (int windowsize, int rootdimension) {int Measurespec;switch (rootdimension) {  Case ViewGroup.LayoutParams.MATCH_PARENT:  //Window can ' t resize. Force root view to be windowsize.  Measurespec = Measurespec.makemeasurespec (windowsize, measurespec.exactly);  Break;case ViewGroup.LayoutParams.WRAP_CONTENT:  //Window can resize. Set max size for root view.  Measurespec = Measurespec.makemeasurespec (windowsize, measurespec.at_most);  Break;default:  //Window wants to is an exact size. Force root view to is that size.  Measurespec = Measurespec.makemeasurespec (rootdimension, measurespec.exactly);  break;} return measurespec;}
Through the above code, the Measurespec of the top-level container Decorview is very clear, in particular, it follows the following rules:

According to the width and height parameters of the Layoutparams,

layoutparams.match_parent: Its mode is exact mode, size is the size of the window

layoutparams.wrap_content: Its mode is the maximum mode, the size is variable, but cannot exceed the size of the window

fixed size (e.g. 100DP): its mode is exact mode, size is the size specified in Layoutparams

measurespec-Application Layer ViewFor application layer view, here is the view in our layout, whose measurespec is created following the rules in the following table


For the above table, here is a detailed explanation. As mentioned earlier, for application-layer View, its measurespec by the parent container's measurespec and self-
The layoutparams of the body, the layoutparams,view of different parent containers and view itself can have a variety of measurespec. This is simply to say, when the view uses a fixed width height, regardless of the parent container's measurespec, the view measurespec is the exact mode and its size follows the size of the layoutparams, when the view's width is Match_ Parent, this time if the parent container's pattern is precision mode, then view is also precision mode and its size is the remaining space of the parent container, if the parent container is the largest mode, then view is the largest mode and its size does not exceed the remaining space of the parent container; When the width of the view is WRAP_ Content, the view mode is always maximized and cannot exceed the remaining space of the parent container, regardless of whether the parent container's pattern is accurate or maximized. You may find that in our analysis we have omitted the unspecified mode, which is mainly used in the case of multiple measure within the system, in general, we do not need to pay attention to this pattern.

support for View wrap_content

Default implementation of View#onmeasure
protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
Setmeasureddimension (Getdefaultsize (Getsuggestedminimumwidth (),
WIDTHMEASURESPEC), Getdefaultsize (Getsuggestedminimumheight (), heightmeasurespec));
}

Attention:
With OnDraw-derived View, you need to override the Onmeasure and set the Wrap_content self-
Body size, otherwise using wrap_content is equivalent to using Match_parent.
Cause analysis: see the table above

So how do you rewrite onmeasure so that view supports wrap_content? See the typical code below to note that Mwidth and mheight in the code refer to the internal specifications of the view under Wrap_content, which should be specified by the custom view interior.

protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec, HEIGHTMEASURESPEC); int widthspecmode = Measurespec.getmode (widthmeasurespec); int widthspecsize = MeasureSpec.getSize (widthmeasurespec); int heightspecmode = Measurespec.getmode (heightmeasurespec); int heightspecsize = Measurespec.getsize (HEIGHTMEASURESPEC); if (Widthspecmode = = Measurespec.at_most && Heightspecmode = = Measurespec.at_most) {setmeasureddimension (mwidth, mheight);} else if (Widthspecmode = = Measurespec.at_most) { Setmeasureddimension (Mwidth, heightspecsize);} else if (Heightspecmode = = measurespec.at_most) {setmeasureddimension (widthspecsize, mheight);}}
measure process for view measure process for view
Simple, Direct completion
ViewGroup's measure process
In addition to the completion of their own measure, will also traverse to call all child measure method, each child and then recursion to execute the process
Direct results of measure
Getmeasuredwidth/height can be correctly obtained to
Note: In some cases, the system may require multiple measure to determine the size

get the View's wide height before rendering

This is a more meaningful question, or a difficult question, with the background: sometimes we need to get its width in view rendering, typically we want to get the width of the view in OnCreate, OnStart, Onresume. If you have tried, you will find that this time the view is not measure good, the width of the high is 0, that exactly what to do to correctly obtain its width, the following three ways

activity/view#onwindowfocuschanged : This method shows that the View has been initialized, and the width is ready.
view.post (runnable) : A runnable can be posted to the end of the message queue by post, and then the view is initialized when Looper calls this runnable
view.measure (int widthmeasurespec, int heightmeasurespec) : View width is obtained by manually going to measure


The first two methods are relatively good to understand and relatively simple, here is the main introduction of the next third method of detailed usage:

Use View.measure to get the width of the view in advance, according to the view of the layoutparams to divide
Match_parent
Directly give up, can not measure out the specific width of the high
Specific values (DP/PX)
For example, the width and height are 100px, the following measure:
int widthmeasurespec = Measurespec.makemeasurespec (+, measurespec.exactly);
int heightmeasurespec = Measurespec.makemeasurespec (+, measurespec.exactly);
View.measure (Widthmeasurespec, Heightmeasurespec);
Wrap_content
The following measure:
int widthmeasurespec = Measurespec.makemeasurespec ((1 <<)-1, measurespec.at_most);
int heightmeasurespec = Measurespec.makemeasurespec ((1 <<)-1, measurespec.at_most);
View.measure (Widthmeasurespec, Heightmeasurespec);

Note (1 << 30)-1, by analyzing the implementation of the MEASURESPEC can be known that the size of the view using 30-bit binary representation, that is, the maximum is 30 1 is 2^30-1, that is (1 << 30)-1, in the maximized mode, we use The maximum value that view can theoretically support to construct measurespec is reasonable.

On the measure of the view, there are two wrong usages on the network, such as, why is wrong, first violate the system's internal implementation specification (because cannot pass the wrong measurespec to obtain the legal Specmode thus causes measure error), Second, there is no guarantee that the correct results will be measure.

The first type of error usage
int widthmeasurespec = Measurespec.makemeasurespec ( -1, measurespec.unspecified);
int heightmeasurespec = Measurespec.makemeasurespec ( -1, measurespec.unspecified);
View.measure (Widthmeasurespec, Heightmeasurespec);

The second type of error usage
View.measure (Layoutparams.wrap_content, layoutparams.wrap_content)

the layout process of the View

The main function of layout
The ViewGroup is used to determine the position of the child element.
Process
When the position of the viewgroup is determined, it will traverse all the child in OnLayout and call its layout. OnLayout will be called in layout.
Key methods
public void layout (int l, int t, int r, int b)
OnLayout (changed, L, T, R, B)

construct a special View

question : How do I make getwidth and getmeasuredwidth return a different value?
private void Setchildframe (View child, int left, int top, int measuredwidth, int measureheight) {
Child.layout (left, top, left + measuredwidth, top + measureheight);
}
int width = Right-left;
int height = Bottom-top
Method
Place the view anywhere in the onlayout of the parent container by Child.layout
Modify the Mleft/mright/mtop/mbottom in your own onlayout

the draw process for View

The approximate flow of draw
A. painting background background.draw (canvas)
B. Draw yourself (OnDraw)
C. drawing children (Dispatchdraw)
D. drawing decorations (Ondrawscrollbars)
Note:
Dispatchdraw will iterate through the draw that calls all child, so the draw event is passed down one layer at a

two custom View Custom View Type

Inherit View rewrite OnDraw
Inherit ViewGroup to derive specific Layout
Inherit a specific View (e.g. TextView, ListView)
Inherit specific Layout (e.g. LinearLayout)

Customizing View notesLet view support Wrap_content
If necessary, let your view support padding
Try not to use Handler in view, no need
If the thread or animation in the view needs to be stopped in time, refer to View#ondetachedfromwindow
When a view has a sliding nesting situation, it needs to handle the sliding conflict.

More InformationHttp://blog.csdn.net/singwhatiwanna
Https://github.com/singwhatiwanna

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.