Android View measure (3) Common method: androidmeasure
ViewGroup. measureChildren ()
ViewGroup. measureChild ()
ViewGroup. measureChildWithMargins ()
/*** Ask one of the children of this view to measure itself, taking into * account both the MeasureSpec requirements for this view and its padding * and margins. the child must have MarginLayoutParams The heavy lifting is * done in getChildMeasureSpec. ** @ param child The child to measure * @ param parentWidthMeasureSpec The width requirements for this view * @ param widthUsed Extra space that has been used up by the parent * horizontally (possibly by other children of the parent) * @ param parentHeightMeasureSpec The height requirements for this view * @ param heightUsed Extra space that has been used up by the parent * vertically (possibly by other children of the parent) */protected void measureChildWithMargins (View child, int parentWidthMeasureSpec, int widthUsed, int second, int heightUsed) {// type conversion final MarginLayoutParams lp = (marginlayoutyoutparams child. getLayoutParams (); // 2 getChildMeasureSpec method final int childWidthMeasureSpec = getChildMeasureSpec (parentWidthMeasureSpec, mPaddingLeft + mPaddingRight + lp. leftMargin + lp. rightMargin + widthUsed, lp. width); final int childHeightMeasureSpec = getChildMeasureSpec (parentHeightMeasureSpec, mPaddingTop + mPaddingBottom + lp. topMargin + lp. bottomMargin + heightUsed, lp. height); child. measure (childWidthMeasureSpec, childHeightMeasureSpec );}
This method performs the Measure operation on the Child view passed by the first parameter.
1. The passed sub-view LayoutParams must be or inherit from MarginLayoutParams. Otherwise, a conversion exception is thrown.
/** * Does the hard part of measureChildren: figuring out the MeasureSpec to * pass to a particular child. This method figures out the right MeasureSpec * for one dimension (height or width) of one child view. * * The goal is to combine information from our MeasureSpec with the * LayoutParams of the child to get the best possible results. For example, * if the this view knows its size (because its MeasureSpec has a mode of * EXACTLY), and the child has indicated in its LayoutParams that it wants * to be the same size as the parent, the parent should ask the child to * layout given an exact size. * * @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.FILL_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.FILL_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 him have it resultSize = childDimension; resultMode = MeasureSpec.EXACTLY; } else if (childDimension == LayoutParams.FILL_PARENT) { // Child wants to be our size... find out how big it should // be resultSize = 0; resultMode = MeasureSpec.UNSPECIFIED; } else if (childDimension == LayoutParams.WRAP_CONTENT) { // Child wants to determine its own size.... find out how // big it should be resultSize = 0; resultMode = MeasureSpec.UNSPECIFIED; } break; } return MeasureSpec.makeMeasureSpec(resultSize, resultMode); }
Protected void measureChildWithMargins (View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {// 1 .... // 2 getChildMeasureSpec method final int childWidthMeasureSpec = getChildMeasureSpec (parentWidthMeasureSpec, mPaddingLeft + mPaddingRight + lp. leftMargin + lp. rightMargin + widthUsed, lp. width );}
Call this method to see the specific meanings of the three parameters.
1. spec: The specification required by this view [parentWidthMeasureSpec]
2. padding: the padding value of the current ViewGroup view and the margin value of the imported sub-view [mPaddingLeft + mPaddingRight + lp. leftMargin + lp. rightMargin + widthUsed ]? WidthUsed
3. childDimension: the input parameter view. The expected value is "lp. width]
** For example
Extended: MeasureSpec method and splicing Method
/** * Utility to reconcile a desired size with constraints imposed by a MeasureSpec. * Will take the desired size, unless a different size is imposed by the constraints. * * @param size How big the view wants to be * @param measureSpec Constraints imposed by the parent * @return The size this view should be. */ public static int resolveSize(int size, int measureSpec) { int result = size; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) { case MeasureSpec.UNSPECIFIED: result = size; break; case MeasureSpec.AT_MOST: result = Math.min(size, specSize); break; case MeasureSpec.EXACTLY: result = specSize; break; } return result; }
/** * Creates a measure specification based on the supplied size and mode. * * The mode must always be one of the following: * <ul> * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li> * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li> * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li> * </ul> * * @param size the size of the measure specification * @param mode the mode of the measure specification * @return the measure specification based on size and mode */ public static int makeMeasureSpec(int size, int mode) { return size + mode; }
/** * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the * measured width and measured height. Failing to do so will trigger an * exception at measurement time.</p> * * @param measuredWidth the measured width of this view * @param measuredHeight the measured height of this view */ protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) { mMeasuredWidth = measuredWidth; mMeasuredHeight = measuredHeight; mPrivateFlags |= MEASURED_DIMENSION_SET; } /** * The width of this view as measured in the most recent call to measure(). * This should be used during measurement and layout calculations only. Use * {@link #getWidth()} to see how wide a view is after layout. * * @return The measured width of this view. */ public final int getMeasuredWidth() { return mMeasuredWidth; } /** * The height of this view as measured in the most recent call to measure(). * This should be used during measurement and layout calculations only. Use * {@link #getHeight()} to see how tall a view is after layout. * * @return The measured height of this view. */ public final int getMeasuredHeight() { return mMeasuredHeight; }