The basic process of measure
- The drawing process of View starts from
ViewRoot
theperformTraversals
method of . It goes through three processes of measure, layout and draw to finally draw a View.
- measure: measure the width and height of the View
- layout: Determine the position of the View in the parent container
- draw: Draw the View on the screen.
performTraversals
Workflow:
- The parent container is
onMeasure
in, it will traverse the method of calling the child Viewmeasure
. - After all child Views are
measure
completed, the layout process will be entered, and the calling process ismeasure
similar. layout
After the process is completed, the process is finally entereddraw
, and the process ismeasure
similar, butperformDraw
the transfer is realized by the methoddraw
in thedispatchDraw
method.
- The parent container is
Only after the Measure is completed, the measured width and height of the View can be passed
getMeasureWidth
andgetMeasureHeight
obtained. They are equivalent to the final width and height of the View in almost all cases, except in special cases.- Similarly, after the Layout is completed, the positions of the four vertices of the View can be obtained, and the final width and height of the View can be obtained through and
getWidth
.getHeight
- Similarly, after the Layout is completed, the positions of the four vertices of the View can be obtained, and the final width and height of the View can be obtained through and
DecorView is the top-level View.
- Under normal circumstances, it will contain a vertical linear layout inside, with the title bar above and the content area below.
- The layout file set in the Activity is
setContentView
actually added to the content area. - The id of the content area can be obtained, and its ID is
android.R.id.content
the View we set for the first child View. - DecorView is one
FramLayout
, all events of the View layer go through firstDecorView
, and then are distributed level by level.
MeasureSpec
Take a look at the source code roughly:
public static class MeasureSpec { /** @hide */ @IntDef({UNSPECIFIED, EXACTLY, AT_MOST}) @Retention(RetentionPolicy.SOURCE) public @interface MeasureSpecMode {} 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(@IntRange(from = 0, to = (1 << View.MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode) { if (sUseBrokenMakeMeasureSpec) { return size + mode; } else { return (size & ~MODE_MASK) | (mode & MODE_MASK); } } } @MeasureSpecMode public static int getMode(int measureSpec) { //noinspection ResourceType return (measureSpec & MODE_MASK); } public static int getSize(int measureSpec) { return (measureSpec & ~MODE_MASK); }
Bit operations are widely used in Android source code, such as various FLAGs of Intent. They have higher efficiency and lower memory overhead.
SpecMode has three categories:
EXACTLY
:layout_width
/layout_height
Specify as a specific value ormatch_parent
, the parent container will specify an exact SpecSize.AT_MOST
:layout_width
/layout_height
Specified aswrap_content
, the parent container will specify a SpecSize of the available size, the size of the View cannot be larger than this value. The specific value depends on the specific implementation of different Views.UNSPECIFIED
: The parent container does not have any restrictions on the View. Developers will use it when drawing custom Views.
MeasureSpec
andLayoutParams
For DecorView, it
MeasureSpec
is determined by the size of the window and itselfLayoutParams
.LayoutParams.MATCH_PARENT
: Window can't resize. Froce root view to be windowSize. EXACTLY mode, the (forced) size is the size of the window.LayoutParams.WRAP_CONTENT
: Window can resize. Set max size for root view. AT_MOST mode, will set the maximum size for root view, but cannot exceed the window size.- Fixed size (such as specific dp value): Window wants to be an exact size. Force root view to be that size. EXACTLY mode, (force) root view size is the specified size.
The ordinary View is determined by the parent container
MeasureSpec
and itselfLayoutParams
, and is also related to the parent containerpading
and itselfmargin
.
MeasureSpec
The creation rules of ordinary ViewgetChildMeasureSpec
can be understood by viewing the source code:Father Spec View size View的SpecSize View's SpecMode EXACTLY
Fixed value>=0 Fixed value EXACTLY
EXACTLY
MATCH_PARENT
父SpecSize-padding EXACTLY
EXACTLY
WRAP_CONTENT
父SpecSize-padding AT_MOST
AT_MOST
Fixed value>=0 Fixed value EXACTLY
AT_MOST
MATCH_PARENT
父SpecSize-padding AT_MOST
AT_MOST
WRAP_CONTENT
父SpecSize-padding AT_MOST
UNSPECIFIED
Fixed value>=0 Fixed value EXACTLY
UNSPECIFIED
MATCH_PARENT
0 UNSPECIFIED
UNSPECIFIED
WRAP_CONTENT
0 UNSPECIFIED