Android View System parsing (bottom)

Source: Internet
Author: User
Tags message queue

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 to the lower part, outline for example the following

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

Define your own view

Define the View category yourself

Define your own View notes


the drawing process of a view first knowledge of Viewroot

Viewroot
corresponding to the Viewrootimpl class, is the link between WindowManager and Decorview.


Activitythread when the activity object is created, the Decorview is added to the window in the same time viewrootimpl the creation and creation and Decorview of the connection.


root = new Viewrootimpl (View.getcontext (), display);
Root.setview (view, Wparams, Panelparentview);
The drawing process for view begins with the performtraversals of Viewroot, which is the code flow:
Performmeasure, Measure, onmeasure
PerformLayout, Layout, onlayout
Performdraw, Draw, OnDraw

composition of the activity interface

Decorview as the top view. Under normal circumstances it has the upper and lower components (details will be related to the API version number and theme). Above is title. Here is the content, in the activity we call Setcontentview to set the view is actually added to the content, and how to get content, can be: ViewGroup content= (ViewGroup ) Findviewbyid (Android. r.id.content), how to get the view we set, can be like this: Content.getchildat (0). At the same time, through the source code we can know that 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.

watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvc2luz3doyxrpd2fubme=/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma== /dissolve/70/gravity/southeast "/>

Measurespec

Measurespec
Encapsulates the restrictions on the layout of a parent container on a view. The interior provides a wide range of information (Specmode, specsize), specsize refers to the size of the reference under a certain specmode, of which Specmode has the following three kinds:
UNSPECIFIED
Parent container Incorrect view has no restrictions whatsoever. How big will it be?
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 packaging/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

Here's a look at some of the constants inside the Measurespec, and it's not hard to understand how MEASURESPEC works with the following code

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 form 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 will be able to 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, in order to understand 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;}
With the above code, the MEASURESPEC process of the top-level container Decorview is very clear, and in detail its adherence to the following rules, for example:

According to its layoutparams, the width of the high of the number of points.

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

layoutparams.wrap_content: Its mode is maximum mode. Variable size. However, you cannot exceed the size of the form

fixed size (for example, 100DP): Its mode is precision mode. Size is the size specified in Layoutparams

measurespec-Application Layer ViewFor application layer view, here is the view in our layout. The creation of its measurespec follows the rules in the following table


For the above table, here is a detailed explanation. Already mentioned earlier. for application layer View. Its measurespec by the parent container's measurespec and self-
Layoutparams to determine the difference between the parent container and the view itself. Layoutparams. View can have a variety of measurespec.

Here's a simple point, when the view is fixed to a wide height. Regardless of the parent container's measurespec. The measurespec of the view are accurate and the size follows the size of the layoutparams, and when the width of the view is match_parent, it is assumed that the pattern of the parent container is precision mode. Then view is also a precision mode and its size is the remaining space of the parent container. Assuming that the parent container is the maximum mode, view is also 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 mode of the view is always maximized and the size cannot exceed the remaining space of the parent container, regardless of whether the parent container's mode is accurate or maximized.

You may find out that the unspecified pattern is missing from our analysis. This mode is mainly used in the case of multiple measure within the system, in general, we do not need to pay attention to this mode.

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? Take a look at the typical code below, and be aware that Mwidth and mheight in the code refer to the internal specifications of the view under Wrap_content. This specification (wide height) should be specified by the internal definition of the view itself.

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, complete directly
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 return to run this process
Direct results of measure
Getmeasuredwidth/height is able to obtain the correct
Note: In some cases, the system may require multiple measure ability to determine the size

get the View's wide height before rendering

This is a more meaningful question. Or a difficult question, the background is: sometimes we need to get its width in view rendering. The typical scenario is that we want to get the width of the view in OnCreate, OnStart, and Onresume.

Let's say you've tried, you'll find. This time the view is not measure good, the width of the height is 0. What the hell do you do? To get its wide height correctly, here are 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 wait for Looper to call this runnable. The view is already initialized.
view.measure (int widthmeasurespec, int heightmeasurespec) : View width is obtained by manually going to measure


The first two methods are better understood and simpler, here is the third method of the detailed use of the method:

Use View.measure to get the view's wide height in advance. According to the layoutparams of the view
Match_parent
Give up directly. Unable to measure out the detailed width and height
Detailed VALUES (DP/PX)
For example, the width height is 100px, such as the following measure:
int widthmeasurespec = Measurespec.makemeasurespec (+, measurespec.exactly);
int heightmeasurespec = Measurespec.makemeasurespec (+, measurespec.exactly);
View.measure (Widthmeasurespec, Heightmeasurespec);
Wrap_content
For example 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 that (1 << 30)-1, by analyzing the implementation of the MEASURESPEC, you can know that the size of the view is represented by a 30-bit binary. That is, the maximum is 30 1 namely 2^30-1, namely (1 << 30) 1, in the maximized mode, we can theoretically support the maximum value to construct the MEASURESPEC is reasonable.

About the measure of the view. There are two error usage methods on the network. For example, the following, why is wrong, the first violation of the system's internal implementation specifications (because the wrong measurespec can not be obtained by the legal specmode resulting in measure error), and secondly can not guarantee that the correct results will be measure.

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

Another way to use errors
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 different values?
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 view to any location in the parent container's onlayout by child.layout
Change 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 traverse draw that calls all of the child, so the draw event is passed down one layer at a

two own definition View define the view type yourself

Inherit View rewrite OnDraw
Inherit ViewGroup to derive specific Layout
Inherit a specific View (for example, TextView, ListView)
Inherit specific Layout (for example, LinearLayout)

define your own view notesLet view support Wrap_content
If necessary, let your view support padding
Try not to use Handler in view, not required
The view assumes a thread or animation. Need to stop in time, take a test View#ondetachedfromwindow
When the view has a sliding nesting situation. Need to handle the sliding conflict.

a lot of other informationHttp://blog.csdn.net/singwhatiwanna
Https://github.com/singwhatiwanna

Android View System parsing (bottom)

Related Article

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.