In the [Android] Custom View series – Drawing Process, we measured the width and height according to certain rules during the measurement process, and then saved the result through setMeasuredDimension().

So the main rules here are MeasureSpec and LayoutParams

MeasureSpec is????

** * A MeasureSpec encapsulates the layout requirements passed from parent to child. * Each MeasureSpec represents a requirement for either the width or the height. * A MeasureSpec is comprised of a size and a mode. There are three possible modes: * UNSPECIFIED * The parent has not imposed any constraint on the child. It can be whatever size it wants. * EXACTLY * The parent has determined an exact size for the child. The child is going to be given * those bounds regardless of how big it wants to be. * AT_MOST * The child can be as large as it wants up to the specified size. */Copy the code

1.MeasureSpec specifies the width and height of a child View. MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec There are three modes: UNSPECIFIED- It can be whatever size It wants - For example, the size of the recyclerView child View is UNSPECIFIED (regardless of the size of the parent View) How big is wants to be, an exact size), AT_MOST - as large as it wants up to the specified size.Copy the code

However, for us developers, we know that the size of a View should be determined by layout_width and layout_height.

Yes and no. In fact, for any View (including the ViewGroup), the final size is determined by the parent View’s requirements (MeasureSpec) and the child View’s own requirements (Layoutparams-layout_width & layout_height). How was it decided?

/** * @param spec The requirements for this view * @param padding The padding of this view for the current dimension and  * margins, if applicable * @param childDimension How big the child wants to be in the current * dimension * @return a MeasureSpec integer for the child */ public static int getChildMeasureSpec(int spec, int padding, int childDimension) { int specMode = MeasureSpec.getMode(spec); int specSize = MeasureSpec.getSize(spec); int size = Math.max(0, specSize - padding); int resultSize = 0; int resultMode = 0; switch (specMode) { // Parent has imposed an exact size on us case MeasureSpec.EXACTLY: if (childDimension >= 0) { resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size. So be it. resultSize = size; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } break; // Parent has imposed a maximum size on us case MeasureSpec.AT_MOST: if (childDimension >= 0) { // Child wants a specific size... so be it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size, but our size is not fixed. // Constrain child to not be bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size. It can't be // bigger than us. resultSize = size; resultMode = MeasureSpec.AT_MOST; } break; // Parent asked to see how big we want to be case MeasureSpec.UNSPECIFIED: if (childDimension >= 0) { // Child wants a specific size... let them have it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.MATCH_PARENT) { // Child wants to be our size... find out how big it should // be resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size.... find out how // big it should be resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size; resultMode = MeasureSpec.UNSPECIFIED; } break; } //noinspection ResourceType return MeasureSpec.makeMeasureSpec(resultSize, resultMode); }Copy the code

The above code logic is very simple, the source notes are also very close, please be patient to read. Then look at the summary table below, don’t memorize the table below.)

ChildDimension (size of the child View), size(remaining space of the parent View)

EXACTLY AT_MOST UNSPECIFIED
Specific value (i.e. childDimension ≥ 0) EXACTLY size :childDimension EXACTLY size :childDimension EXACTLY size :childDimension
match_parent B :EXACTLY Mode :AT_MOST Size :size Pattern: UNSPECIFIED size: the sUseZeroUnspecifiedMeasureSpec? 0 : size
wrap_content Mode :AT_MOST Size :size Mode :AT_MOST Size :size Pattern: UNSPECIFIED size: the sUseZeroUnspecifiedMeasureSpec? 0 : size

Why is onInterceptTouchEvent() not executed once it returns true in one event sequence, and then again in the next?

I haven’t found a definitive answer to this question yet. The onInterceptTouchEvent() will not be emitted after the mGroupFlags flag is changed. And resetTouchState() is called to reset the state at UP/CANCEL/HOVER_MOVE and at the beginning of the next sequence of events (i.e., DOWN). This will also touch onInterceptTouchEvent().

MeasureSpec content and the above questions welcome to the comments section ~