Android View system analysis (below), androidview

Source: Internet
Author: User

Android View system analysis (below), androidview


Android View parsing series:

Analysis of Android View system (I)

This section describes the basic knowledge of a View, sliding, elastic sliding, sliding conflict resolution, and event distribution.

Analysis of Android View system (below)

This article introduces the Framework layer principle of View, three steps and some advanced skills of View: measure, layout, and draw.

This section mainly introduces the lower part. The outline is as follows:

View rendering process

Measure/layout/draw Workflow

Recognizes MeasureSpec and makes appropriate MeasureSpec

Obtain the width and height of the View before rendering.

Construct a special View

Custom View

Custom View category

Notice on creating a custom View


1. View rendering process First glance at ViewRoot

ViewRoot
Corresponding to the ViewRootImpl class, it is the link connecting WindowManager and DecorView.
When the activity object in ActivityThread is created, the DecorView is added to the Window, and the creation of ViewRootImpl is completed and the contact with DecorView is established.
Root = new ViewRootImpl (view. getContext (), display );
Root. setView (view, wparams, panelParentView );
The process of drawing a view starts from the javasmtraversals of ViewRoot. The Code process is as follows:
Define mmeasure-> measure-> onMeasure
Extends mlayout-> layout-> onLayout
Export mdraw-> draw-> onDraw

Composition of the activity Interface

It can be seen that as a top-level View, DecorView generally consists of the upper and lower parts (the specific situation will be related to the api version and Theme). The above is the title, and the following is the content, in the activity, the view set by setContentView is actually added to the content. How can we get the content? ViewGroup group = findViewById (R. android. id. content), how can we get the view we set? It can be like this: group. getChildAt (0 ). At the same time, we can know from the source code that DecorView is actually a FrameLayout. It should be noted that most of the events at the View layer are transmitted from DecorView to our view.


MeasureSpec

MeasureSpec
It encapsulates the layout restrictions of the parent container on the view and provides the wide and high information (SpecMode and SpecSize) internally. SpecSize refers to the reference size in a certain SpecMode, specMode has the following three types:
UNSPECIFIED
The parent container does not have any restrictions on The view.
EXACTLY
The parent container has detected the size required by the view.
AT_MOST
The parent container specifies a size. The view size cannot be greater than this value.
Significance of MeasureSpecs
By packaging SpecMode and SpecSize into an int value, you can avoid excessive object memory allocation. To facilitate the operation, it provides the packaging/unpackaging method.

Implementation of MeasureSpec

MeasureSpec

Represents a 32-bit int Value
Two digits in height represent SpecMode, and 30 digits in height represent SpecSize.

Next, let's take a look at some definitions of constants in MeasureSpec. Through the following code, it is not difficult to understand the working principle of MeasureSpec.

[Java]View plaincopy
  1. Private static final int MODE_SHIFT = 30;
  2. Private static final int MODE_MASK = 0x3 <MODE_SHIFT;
  3. Public static final int UNSPECIFIED = 0 <MODE_SHIFT;
  4. Public static final int EXACTLY = 1 <MODE_SHIFT;
  5. Public static final int AT_MOST = 2 <MODE_SHIFT;
  6. Public static int makeMeasureSpec (int size, int mode ){
  7. If (sUseBrokenMakeMeasureSpec ){
  8. Return size + mode;
  9. } Else {
  10. Return (size &~ MODE_MASK) | (mode & MODE_MASK );
  11. }
  12. }
  13. Public static int getMode (int measureSpec ){
  14. Return (measureSpec & MODE_MASK );
  15. }
  16. Public static int getSize (int measureSpec ){
  17. Return (measureSpec &~ MODE_MASK );
  18. }
MeasureSpec and LayoutParamsFor DecorView, its MeasureSpec is determined by the size of the window and its own LayoutParams.
For the application layer View, the MeasureSpec is jointly determined by the MeasureSpec of the parent container and its own LayoutParams.
Once MeasureSpec is determined, onMeasure can determine its own width and height.
MeasureSpec-DecorView

Here we will analyze the process of generating the MeasureSpec of the top-level container DecorView.

ChildWidthMeasureSpec = getRootMeasureSpec (baseSize, lp. width );
ChildHeightMeasureSpec = getRootMeasureSpec (desired1_wheight, lp. height );
Extends mmeasure (childWidthMeasureSpec, childHeightMeasureSpec );

The above Code describes the process of generating DecorView's MeasureSpec. For a clearer understanding, let's continue to look at it.

[Java]View plaincopy
  1. Private static int getRootMeasureSpec (int windowSize, int rootDimension ){
  2. Int measureSpec;
  3. Switch (rootDimension ){
  4. Case ViewGroup. LayoutParams. MATCH_PARENT:
  5. // Window can't resize. Force root view to be windowSize.
  6. MeasureSpec = MeasureSpec. makeMeasureSpec (windowSize, MeasureSpec. EXACTLY );
  7. Break;
  8. Case ViewGroup. LayoutParams. WRAP_CONTENT:
  9. // Window can resize. Set max size for root view.
  10. MeasureSpec = MeasureSpec. makeMeasureSpec (windowSize, MeasureSpec. AT_MOST );
  11. Break;
  12. Default:
  13. // Window wants to be an exact size. Force root view to be that size.
  14. MeasureSpec = MeasureSpec. makeMeasureSpec (rootDimension, MeasureSpec. EXACTLY );
  15. Break;
  16. }
  17. Return measureSpec;
  18. }
Through the above Code, the process of generating the MeasureSpec of the top-level container DecorView is very clear. Specifically, it complies with the following rules:

According to the parameter of its LayoutParams,

LayoutParams. MATCH_PARENT: The mode is precise, and the size is the size of the window.

LayoutParams. WRAP_CONTENT: The maximum mode is used. The window size cannot be exceeded.

Fixed size(For example, 100dp): The exact mode is used, and the size is the size specified in LayoutParams.

MeasureSpec-Application Layer ViewFor the application layer View, this refers to the view in our layout. The creation of the MeasureSpec follows the rules in the following table.


For the above table, here we will make a detailed description. As mentioned above, for the application layer View, the MeasureSpec consists of the MeasureSpec and
The LayoutParams of the parent container and the LayoutParams of the view itself are determined together. The view can have multiple MeasureSpec types. Here, when a view uses a fixed width and height, regardless of the MeasureSpec of the parent container, the view's MeasureSpec is in exact mode and its size follows the size in Layoutparams; when the width and height of a view are match_parent, if the parent container adopts the precise mode, the view is also the precise mode and its size is the remaining space of the parent container, if the parent container is in the maximum mode, view is also in the maximum Mode and Its size does not exceed the remaining space of the parent container. When the width and height of view is wrap_content, whether the mode of the parent container is accurate or maximized, the view mode is always maximized and the size cannot exceed the remaining space of the parent container. You may find that the Unspecified mode is missing in our analysis. This mode is mainly used for multiple internal measurements within the system. In general, we do not need to pay attention to this mode.

Support View wrap_content

View # default onMeasure implementation
Protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec ){
SetMeasuredDimension (getDefaultSize (getSuggestedMinimumWidth (),
WidthMeasureSpec), getDefaultSize (getSuggestedMinimumHeight (), heightMeasureSpec ));
}

Note:
For a View derived from onDraw, you must override onMeasure and set
Body Size, otherwise wrap_content is equivalent to match_parent.
Cause Analysis: See the table above.

So how can I rewrite onMeasure to allow view to support wrap_content? Please refer to the following typical code. The mWidth and mHeight in the Code refer to the internal specifications of view under wrap_content, and this specification (width and height) it should be specified in the Custom view.

[Java]View plaincopy
  1. Protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec ){
  2. Super. onMeasure (widthMeasureSpec, heightMeasureSpec );
  3. Int widthSpecMode = MeasureSpec. getMode (widthMeasureSpec );
  4. Int widthSpecSize = MeasureSpec. getSize (widthMeasureSpec );
  5. Int heightSpecMode = MeasureSpec. getMode (heightMeasureSpec );
  6. Int heightSpecSize = MeasureSpec. getSize (heightMeasureSpec );
  7. If (widthSpecMode = MeasureSpec. AT_MOST & heightSpecMode = MeasureSpec. AT_MOST ){
  8. SetMeasuredDimension (mWidth, mHeight );
  9. } Else if (widthSpecMode = MeasureSpec. AT_MOST ){
  10. SetMeasuredDimension (mWidth, heightSpecSize );
  11. } Else if (heightSpecMode = MeasureSpec. AT_MOST ){
  12. SetMeasuredDimension (widthSpecSize, mHeight );
  13. }
  14. }
Measure Process of View Measure Process of view
Simple and complete directly
Measure Process of ViewGroup
In addition to completing your own measure, it also traverses and calls all the child's measure methods. Each child then recursively executes this process.
Direct result of measure:
GetMeasuredWidth/Height can be obtained correctly
Note: In some cases, the system may need to perform multiple measure operations to determine the size.

Obtain the width and height of the View before rendering.

This is a meaningful question or a difficult question. The background is: Sometimes we need to get the width and height before rendering the view. A typical situation is, we want to get the width and height of the view in onCreate, onStart, and onResume. If you have tried it, you will find that the view is not good at measure and the width and height are all 0 at this time. How can we get its width and height correctly? Three methods are provided below.

Activity/View # onWindowFocusChanged: This method indicates that the view has been initialized and the width and height are ready.
View. post (runnable): You can use post to ship a runnable to the end of the message queue, and wait for Logoff to call this runnable. The view has also been initialized.
View. measure (int widthMeasureSpec, int heightMeasureSpec): Manually go to measure to view the width and height of the view.


The first two methods are easy to understand. Here we will introduce the detailed usage of the third method:

View. measure is used to obtain the width and height of the view in advance.
Match_parent
Directly give up, unable to measure the specific width and height
Specific value (dp/px)
For example, if the width and height are both 100px, the following measure:
Int widthMeasureSpec = MeasureSpec. makeMeasureSpec (100, MeasureSpec. EXACTLY );
Int heightMeasureSpec = MeasureSpec. makeMeasureSpec (100, MeasureSpec. EXACTLY );
View. measure (widthMeasureSpec, heightMeasureSpec );
Wrap_content
The following measure:
Int widthMeasureSpec = MeasureSpec. makeMeasureSpec (1 <30)-1, MeasureSpec. AT_MOST );
Int heightMeasureSpec = MeasureSpec. makeMeasureSpec (1 <30)-1, MeasureSpec. AT_MOST );
View. measure (widthMeasureSpec, heightMeasureSpec );

Note that (1 <30)-1, by analyzing the implementation of MeasureSpec, we can know that the view size is represented by 30-bit binary, that is to say, the maximum value is 30 1, that is, 2 ^ 30-1, that is, (1 <30)-1. In the maximum mode, it is reasonable to use the maximum value supported by view to construct MeasureSpec.

There are two incorrect usage of view measure on the network, first, it violates the internal implementation specifications of the system (because the legal SpecMode cannot be obtained through the wrong MeasureSpec, resulting in a measure error). Second, it cannot be guaranteed that the correct result can be returned.

First error
Int widthMeasureSpec = MeasureSpec. makeMeasureSpec (-1, MeasureSpec. UNSPECIFIED );
Int heightMeasureSpec = MeasureSpec. makeMeasureSpec (-1, MeasureSpec. UNSPECIFIED );
View. measure (widthMeasureSpec, heightMeasureSpec );

Second Error
View. measure (LayoutParams. WRAP_CONTENT, LayoutParams. WRAP_CONTENT)

View layout Process

Layout
ViewGroup is used to determine the position of child elements.
Process
When the position of the viewgroup is determined, it traverses all the child in onLayout and calls its layout. In layout, onLayout is called.
Key Methods
Public void layout (int l, int t, int r, int B)
OnLayout (changed, l, t, r, B)

Construct a special View

Problem: How to 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
In onLayout of the parent container, use child. layout to place the view to any location.
Modify mLeft/mRight/mTop/mBottom in onLayout.

View draw Process

General process of draw
A.Draw backgroundBackground. draw (canvas)
B.Draw yourself(OnDraw)
C.Draw children(DispatchDraw)
D.Draw Decoration(OnDrawScrollBars)
Note:
DispatchDraw will traverse and call all child draw, so that the draw event will be passed on layer by layer.

Ii. Custom View Custom View type

Override onDraw by inheriting View
Inherit from ViewGroup to derive a specific Layout
Inherit specific views (such as TextView and ListView)
Inherit specific Layout (such as LinearLayout)

Notice on creating a custom ViewAllow view to support wrap_content
If necessary, make your view support padding
Do not use Handler in view as much as possible, not necessary
If a thread or animation exists in the view, stop it in time. For details, refer to View # onDetachedFromWindow.
When a view has a sliding nested state, you must handle the sliding conflict.

More information http://blog.csdn.net/singwhatiwanna
Https://github.com/singwhatiwanna

Reprinted please indicate Source: http://blog.csdn.net/singwhatiwanna/article/details/38426471 (from singwhatiwanna's csdn blog)

Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.

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.