List of usage examples for android.view View measure
public final void measure(int widthMeasureSpec, int heightMeasureSpec)
This is called to find out how big a view should be.
From source file:administrator.example.com.myscrollview.VerticalViewPager.java
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // For simple implementation, or internal size is always 0. // We depend on the container to specify the layout size of // our view. We can't really know what it is since we will be // adding and removing different arbitrary views and do not // want the layout to change as this happens. setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)); // Children are just made to fill our space. int childWidthSize = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); /*/* www .j av a 2s.c o m*/ * Make sure all children have been properly measured. Decor views first. * Right now we cheat and make this less complicated by assuming decor * views won't intersect. We will pin to edges based on gravity. */ int size = getChildCount(); for (int i = 0; i < size; ++i) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp != null && lp.isDecor) { final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; Log.d(TAG, "gravity: " + lp.gravity + " hgrav: " + hgrav + " vgrav: " + vgrav); int widthMode = MeasureSpec.AT_MOST; int heightMode = MeasureSpec.AT_MOST; boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM; boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT; if (consumeVertical) { widthMode = MeasureSpec.EXACTLY; } else if (consumeHorizontal) { heightMode = MeasureSpec.EXACTLY; } /* end of if */ final int widthSpec = MeasureSpec.makeMeasureSpec(childWidthSize, widthMode); final int heightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, heightMode); child.measure(widthSpec, heightSpec); if (consumeVertical) { childHeightSize -= child.getMeasuredHeight(); } else if (consumeHorizontal) { childWidthSize -= child.getMeasuredWidth(); } /* end of if */ } /* end of if */ } /* end of if */ } /* end of for */ mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); // Make sure we have created all fragments that we need to have shown. mInLayout = true; populate(); mInLayout = false; // Page views next. size = getChildCount(); for (int i = 0; i < size; ++i) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { if (DEBUG) Log.v(TAG, "Measuring #" + i + " " + child + ": " + mChildWidthMeasureSpec); final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp == null || !lp.isDecor) { child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); } /* end of if */ } /* end of if */ } /* end of for */ }
From source file:cn.ismartv.tvrecyclerview.widget.StaggeredGridLayoutManager.java
private void measureChildWithDecorationsAndMargin(View child, int widthSpec, int heightSpec, boolean alreadyMeasured) { calculateItemDecorationsForChild(child, mTmpRect); LayoutParams lp = (LayoutParams) child.getLayoutParams(); widthSpec = updateSpecWithExtra(widthSpec, lp.leftMargin + mTmpRect.left, lp.rightMargin + mTmpRect.right); heightSpec = updateSpecWithExtra(heightSpec, lp.topMargin + mTmpRect.top, lp.bottomMargin + mTmpRect.bottom); final boolean measure = alreadyMeasured ? shouldReMeasureChild(child, widthSpec, heightSpec, lp) : shouldMeasureChild(child, widthSpec, heightSpec, lp); if (measure) { child.measure(widthSpec, heightSpec); }//from w ww . j a v a2s . co m }
From source file:cn.bingoogolapple.swipebacklayout.BGASwipeBackLayout.java
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode != MeasureSpec.EXACTLY) { if (isInEditMode()) { // Don't crash the layout editor. Consume all of the space if specified // or pick a magic number from thin air otherwise. // TODO Better communication with tools of this bogus state. // It will crash on a real device. if (widthMode == MeasureSpec.AT_MOST) { widthMode = MeasureSpec.EXACTLY; } else if (widthMode == MeasureSpec.UNSPECIFIED) { widthMode = MeasureSpec.EXACTLY; widthSize = 300;// ww w . j a va 2 s .co m } } else { throw new IllegalStateException("Width must have an exact value or MATCH_PARENT"); } } else if (heightMode == MeasureSpec.UNSPECIFIED) { if (isInEditMode()) { // Don't crash the layout editor. Pick a magic number from thin air instead. // TODO Better communication with tools of this bogus state. // It will crash on a real device. if (heightMode == MeasureSpec.UNSPECIFIED) { heightMode = MeasureSpec.AT_MOST; heightSize = 300; } } else { throw new IllegalStateException("Height must not be UNSPECIFIED"); } } int layoutHeight = 0; int maxLayoutHeight = -1; switch (heightMode) { case MeasureSpec.EXACTLY: layoutHeight = maxLayoutHeight = heightSize - getPaddingTop() - getPaddingBottom(); break; case MeasureSpec.AT_MOST: maxLayoutHeight = heightSize - getPaddingTop() - getPaddingBottom(); break; } // ======================== START ======================== maxLayoutHeight -= UIUtil.getNavigationBarHeight(mActivity); // ======================== END ======================== float weightSum = 0; boolean canSlide = false; final int widthAvailable = widthSize - getPaddingLeft() - getPaddingRight(); int widthRemaining = widthAvailable; final int childCount = getChildCount(); if (childCount > 2) { Log.e(TAG, "onMeasure: More than two child views are not supported."); } // We'll find the current one below. mSlideableView = null; // First pass. Measure based on child LayoutParams width/height. // Weight will incur a second pass. for (int i = 0; i < childCount; i++) { final View child = getChildAt(i); final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (child.getVisibility() == GONE) { lp.dimWhenOffset = false; continue; } if (lp.weight > 0) { weightSum += lp.weight; // If we have no width, weight is the only contributor to the final size. // Measure this view on the weight pass only. if (lp.width == 0) continue; } int childWidthSpec; final int horizontalMargin = lp.leftMargin + lp.rightMargin; if (lp.width == LayoutParams.WRAP_CONTENT) { childWidthSpec = MeasureSpec.makeMeasureSpec(widthAvailable - horizontalMargin, MeasureSpec.AT_MOST); } else if (lp.width == LayoutParams.MATCH_PARENT) { childWidthSpec = MeasureSpec.makeMeasureSpec(widthAvailable - horizontalMargin, MeasureSpec.EXACTLY); } else { childWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY); } int childHeightSpec; if (lp.height == LayoutParams.WRAP_CONTENT) { childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight, MeasureSpec.AT_MOST); } else if (lp.height == LayoutParams.MATCH_PARENT) { childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight, MeasureSpec.EXACTLY); } else { childHeightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY); } child.measure(childWidthSpec, childHeightSpec); final int childWidth = child.getMeasuredWidth(); final int childHeight = child.getMeasuredHeight(); if (heightMode == MeasureSpec.AT_MOST && childHeight > layoutHeight) { layoutHeight = Math.min(childHeight, maxLayoutHeight); } widthRemaining -= childWidth; canSlide |= lp.slideable = widthRemaining < 0; if (lp.slideable) { mSlideableView = child; } } // Resolve weight and make sure non-sliding panels are smaller than the full screen. if (canSlide || weightSum > 0) { final int fixedPanelWidthLimit = widthAvailable - mOverhangSize; for (int i = 0; i < childCount; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (child.getVisibility() == GONE) { continue; } final boolean skippedFirstPass = lp.width == 0 && lp.weight > 0; final int measuredWidth = skippedFirstPass ? 0 : child.getMeasuredWidth(); if (canSlide && child != mSlideableView) { if (lp.width < 0 && (measuredWidth > fixedPanelWidthLimit || lp.weight > 0)) { // Fixed panels in a sliding configuration should // be clamped to the fixed panel limit. final int childHeightSpec; if (skippedFirstPass) { // Do initial height measurement if we skipped measuring this view // the first time around. if (lp.height == LayoutParams.WRAP_CONTENT) { childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight, MeasureSpec.AT_MOST); } else if (lp.height == LayoutParams.MATCH_PARENT) { childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight, MeasureSpec.EXACTLY); } else { childHeightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY); } } else { childHeightSpec = MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY); } final int childWidthSpec = MeasureSpec.makeMeasureSpec(fixedPanelWidthLimit, MeasureSpec.EXACTLY); child.measure(childWidthSpec, childHeightSpec); } } else if (lp.weight > 0) { int childHeightSpec; if (lp.width == 0) { // This was skipped the first time; figure out a real height spec. if (lp.height == LayoutParams.WRAP_CONTENT) { childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight, MeasureSpec.AT_MOST); } else if (lp.height == LayoutParams.MATCH_PARENT) { childHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight, MeasureSpec.EXACTLY); } else { childHeightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY); } } else { childHeightSpec = MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY); } if (canSlide) { // Consume available space final int horizontalMargin = lp.leftMargin + lp.rightMargin; final int newWidth = widthAvailable - horizontalMargin; final int childWidthSpec = MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY); if (measuredWidth != newWidth) { child.measure(childWidthSpec, childHeightSpec); } } else { // Distribute the extra width proportionally similar to LinearLayout final int widthToDistribute = Math.max(0, widthRemaining); final int addedWidth = (int) (lp.weight * widthToDistribute / weightSum); final int childWidthSpec = MeasureSpec.makeMeasureSpec(measuredWidth + addedWidth, MeasureSpec.EXACTLY); child.measure(childWidthSpec, childHeightSpec); } } } } final int measuredWidth = widthSize; final int measuredHeight = layoutHeight + getPaddingTop() + getPaddingBottom(); setMeasuredDimension(measuredWidth, measuredHeight); mCanSlide = canSlide; if (mDragHelper.getViewDragState() != ViewDragHelper.STATE_IDLE && !canSlide) { // Cancel scrolling in progress, it's no longer relevant. mDragHelper.abort(); } }
From source file:android.support.v7ox.widget.ListPopupWindow.java
/** * <p>Builds the popup window's content and returns the height the popup * should have. Returns -1 when the content already exists.</p> * * @return the content's height or -1 if content already exists *///from w w w . ja va2 s .co m private int buildDropDown() { ViewGroup dropDownView; int otherHeights = 0; if (mDropDownList == null) { Context context = mContext; /** * This Runnable exists for the sole purpose of checking if the view layout has got * completed and if so call showDropDown to display the drop down. This is used to show * the drop down as soon as possible after user opens up the search dialog, without * waiting for the normal UI pipeline to do it's job which is slower than this method. */ mShowDropDownRunnable = new Runnable() { public void run() { // View layout should be all done before displaying the drop down. View view = getAnchorView(); if (view != null && view.getWindowToken() != null) { show(); } } }; mDropDownList = new DropDownListView(context, !mModal); if (mDropDownListHighlight != null) { mDropDownList.setSelector(mDropDownListHighlight); } mDropDownList.setAdapter(mAdapter); mDropDownList.setOnItemClickListener(mItemClickListener); mDropDownList.setFocusable(true); mDropDownList.setFocusableInTouchMode(true); mDropDownList.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { if (position != -1) { DropDownListView dropDownList = mDropDownList; if (dropDownList != null) { dropDownList.mListSelectionHidden = false; } } } public void onNothingSelected(AdapterView<?> parent) { } }); mDropDownList.setOnScrollListener(mScrollListener); if (mItemSelectedListener != null) { mDropDownList.setOnItemSelectedListener(mItemSelectedListener); } dropDownView = mDropDownList; View hintView = mPromptView; if (hintView != null) { // if a hint has been specified, we accomodate more space for it and // add a text view in the drop down menu, at the bottom of the list LinearLayout hintContainer = new LinearLayout(context); hintContainer.setOrientation(LinearLayout.VERTICAL); LinearLayout.LayoutParams hintParams = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, 0, 1.0f); switch (mPromptPosition) { case POSITION_PROMPT_BELOW: hintContainer.addView(dropDownView, hintParams); hintContainer.addView(hintView); break; case POSITION_PROMPT_ABOVE: hintContainer.addView(hintView); hintContainer.addView(dropDownView, hintParams); break; default: Log.e(TAG, "Invalid hint position " + mPromptPosition); break; } // Measure the hint's height to find how much more vertical // space we need to add to the drop down's height. final int widthSize; final int widthMode; if (mDropDownWidth >= 0) { widthMode = MeasureSpec.AT_MOST; widthSize = mDropDownWidth; } else { widthMode = MeasureSpec.UNSPECIFIED; widthSize = 0; } final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, widthMode); final int heightSpec = MeasureSpec.UNSPECIFIED; hintView.measure(widthSpec, heightSpec); hintParams = (LinearLayout.LayoutParams) hintView.getLayoutParams(); otherHeights = hintView.getMeasuredHeight() + hintParams.topMargin + hintParams.bottomMargin; dropDownView = hintContainer; } mPopup.setContentView(dropDownView); } else { dropDownView = (ViewGroup) mPopup.getContentView(); final View view = mPromptView; if (view != null) { LinearLayout.LayoutParams hintParams = (LinearLayout.LayoutParams) view.getLayoutParams(); otherHeights = view.getMeasuredHeight() + hintParams.topMargin + hintParams.bottomMargin; } } // getMaxAvailableHeight() subtracts the padding, so we put it back // to get the available height for the whole window int padding = 0; Drawable background = mPopup.getBackground(); if (background != null) { background.getPadding(mTempRect); padding = mTempRect.top + mTempRect.bottom; // If we don't have an explicit vertical offset, determine one from the window // background so that content will line up. if (!mDropDownVerticalOffsetSet) { mDropDownVerticalOffset = -mTempRect.top; } } else { mTempRect.setEmpty(); } // Max height available on the screen for a popup. final boolean ignoreBottomDecorations = mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED; final int maxHeight = getMaxAvailableHeight(getAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations); if (mDropDownAlwaysVisible || mDropDownHeight == ViewGroup.LayoutParams.MATCH_PARENT) { return maxHeight + padding; } final int childWidthSpec; switch (mDropDownWidth) { case ViewGroup.LayoutParams.WRAP_CONTENT: childWidthSpec = MeasureSpec.makeMeasureSpec( mContext.getResources().getDisplayMetrics().widthPixels - (mTempRect.left + mTempRect.right), MeasureSpec.AT_MOST); break; case ViewGroup.LayoutParams.MATCH_PARENT: childWidthSpec = MeasureSpec.makeMeasureSpec( mContext.getResources().getDisplayMetrics().widthPixels - (mTempRect.left + mTempRect.right), MeasureSpec.EXACTLY); break; default: childWidthSpec = MeasureSpec.makeMeasureSpec(mDropDownWidth, MeasureSpec.EXACTLY); break; } final int listContent = mDropDownList.measureHeightOfChildrenCompat(childWidthSpec, 0, DropDownListView.NO_POSITION, maxHeight - otherHeights, -1); // add padding only if the list has items in it, that way we don't show // the popup if it is not needed if (listContent > 0) otherHeights += padding; return listContent + otherHeights; }
From source file:com.devabit.takestock.ui.widget.FlexboxLayout.java
/** * Sub method for {@link #onMeasure(int, int)} when the main axis direction is vertical * (either from top to bottom or bottom to top). * * @param widthMeasureSpec horizontal space requirements as imposed by the parent * @param heightMeasureSpec vertical space requirements as imposed by the parent * @see #onMeasure(int, int)/* w w w .j ava 2s . co m*/ * @see #setFlexDirection(int) * @see #setFlexWrap(int) * @see #setAlignItems(int) * @see #setAlignContent(int) */ private void measureVertical(int widthMeasureSpec, int heightMeasureSpec) { int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int childState = 0; mFlexLines.clear(); // Determine how many flex lines are needed in this layout by measuring each child. // (Expand or shrink the view depending on the flexGrow and flexShrink attributes in a later // loop) int childCount = getChildCount(); int paddingTop = getPaddingTop(); int paddingBottom = getPaddingBottom(); int largestWidthInColumn = Integer.MIN_VALUE; FlexLine flexLine = new FlexLine(); flexLine.mainSize = paddingTop + paddingBottom; for (int i = 0; i < childCount; i++) { View child = getReorderedChildAt(i); if (child == null) { addFlexLineIfLastFlexItem(i, childCount, flexLine); continue; } else if (child.getVisibility() == View.GONE) { flexLine.itemCount++; addFlexLineIfLastFlexItem(i, childCount, flexLine); continue; } FlexboxLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp.alignSelf == LayoutParams.ALIGN_SELF_STRETCH) { flexLine.indicesAlignSelfStretch.add(i); } int childHeight = lp.height; if (lp.flexBasisPercent != LayoutParams.FLEX_BASIS_PERCENT_DEFAULT && heightMode == MeasureSpec.EXACTLY) { childHeight = Math.round(heightSize * lp.flexBasisPercent); // Use the dimension from the layout_height attribute if the heightMode is not // MeasureSpec.EXACTLY even if any fraction value is set to layout_flexBasisPercent. // There are likely quite few use cases where assigning any fraction values // with heightMode is not MeasureSpec.EXACTLY (e.g. FlexboxLayout's layout_height // is set to wrap_content) } int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin, lp.width); int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin, childHeight); child.measure(childWidthMeasureSpec, childHeightMeasureSpec); // Check the size constraint after the first measurement for the child // To prevent the child's width/height violate the size constraints imposed by the // {@link LayoutParams#minWidth}, {@link LayoutParams#minHeight}, // {@link LayoutParams#maxWidth} and {@link LayoutParams#maxHeight} attributes. // E.g. When the child's layout_height is wrap_content the measured height may be // less than the min height after the first measurement. checkSizeConstraints(child); childState = ViewCompat.combineMeasuredStates(childState, ViewCompat.getMeasuredState(child)); largestWidthInColumn = Math.max(largestWidthInColumn, child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin); if (isWrapRequired(mFlexWrap, heightMode, heightSize, flexLine.mainSize, child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin, lp)) { if (flexLine.itemCount > 0) { mFlexLines.add(flexLine); } flexLine = new FlexLine(); flexLine.itemCount = 1; flexLine.mainSize = paddingTop + paddingBottom; largestWidthInColumn = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; } else { flexLine.itemCount++; } flexLine.mainSize += child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; flexLine.totalFlexGrow += lp.flexGrow; flexLine.totalFlexShrink += lp.flexShrink; // Temporarily set the cross axis length as the largest child width in the column // Expand along the cross axis depending on the mAlignContent property if needed // later flexLine.crossSize = Math.max(flexLine.crossSize, largestWidthInColumn); addFlexLineIfLastFlexItem(i, childCount, flexLine); } determineMainSize(mFlexDirection, widthMeasureSpec, heightMeasureSpec); determineCrossSize(mFlexDirection, widthMeasureSpec, heightMeasureSpec, getPaddingLeft() + getPaddingRight()); // Now cross size for each flex line is determined. // Expand the views if alignItems (or alignSelf in each child view) is set to stretch stretchViews(mFlexDirection, mAlignItems); setMeasuredDimensionForFlex(mFlexDirection, widthMeasureSpec, heightMeasureSpec, childState); }
From source file:com.example.view.VerticalViewPager.java
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // For simple implementation, or internal size is always 0. // We depend on the container to specify the layout size of // our view. We can't really know what it is since we will be // adding and removing different arbitrary views and do not // want the layout to change as this happens. setMeasuredDimension(getDefaultSize(0, widthMeasureSpec), getDefaultSize(0, heightMeasureSpec)); // Children are just made to fill our space. int childWidthSize = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); int childHeightSize = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); /*/*from w w w . ja v a 2s . c om*/ * Make sure all children have been properly measured. Decor views * first. Right now we cheat and make this less complicated by assuming * decor views won't intersect. We will pin to edges based on gravity. */ int size = getChildCount(); for (int i = 0; i < size; ++i) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp != null && lp.isDecor) { final int hgrav = lp.gravity & Gravity.HORIZONTAL_GRAVITY_MASK; final int vgrav = lp.gravity & Gravity.VERTICAL_GRAVITY_MASK; Log.d(TAG, "gravity: " + lp.gravity + " hgrav: " + hgrav + " vgrav: " + vgrav); int widthMode = MeasureSpec.AT_MOST; int heightMode = MeasureSpec.AT_MOST; boolean consumeVertical = vgrav == Gravity.TOP || vgrav == Gravity.BOTTOM; boolean consumeHorizontal = hgrav == Gravity.LEFT || hgrav == Gravity.RIGHT; if (consumeVertical) { widthMode = MeasureSpec.EXACTLY; } else if (consumeHorizontal) { heightMode = MeasureSpec.EXACTLY; } /* end of if */ final int widthSpec = MeasureSpec.makeMeasureSpec(childWidthSize, widthMode); final int heightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, heightMode); child.measure(widthSpec, heightSpec); if (consumeVertical) { childHeightSize -= child.getMeasuredHeight(); } else if (consumeHorizontal) { childWidthSize -= child.getMeasuredWidth(); } /* end of if */ } /* end of if */ } /* end of if */ } /* end of for */ mChildWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidthSize, MeasureSpec.EXACTLY); mChildHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeightSize, MeasureSpec.EXACTLY); // Make sure we have created all fragments that we need to have shown. mInLayout = true; populate(); mInLayout = false; // Page views next. size = getChildCount(); for (int i = 0; i < size; ++i) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { if (DEBUG) Log.v(TAG, "Measuring #" + i + " " + child + ": " + mChildWidthMeasureSpec); final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp == null || !lp.isDecor) { child.measure(mChildWidthMeasureSpec, mChildHeightMeasureSpec); } /* end of if */ } /* end of if */ } /* end of for */ }
From source file:com.google.android.flexbox.FlexboxLayoutManager.java
private int layoutFlexLineMainAxisVertical(FlexLine flexLine, LayoutState layoutState) { assert mFlexboxHelper.mMeasureSpecCache != null; int paddingTop = getPaddingTop(); int paddingBottom = getPaddingBottom(); int parentHeight = getHeight(); int childLeft = layoutState.mOffset; // childRight is used only for the layout is RTL int childRight = layoutState.mOffset; if (layoutState.mLayoutDirection == LayoutState.LAYOUT_START) { childLeft = childLeft - flexLine.mCrossSize; childRight = childRight + flexLine.mCrossSize; }/*from w w w.j av a 2s . c o m*/ int startPosition = layoutState.mPosition; float childTop; // Only used when mFromBottomToTop is true float childBottom; float spaceBetweenItem = 0f; switch (mJustifyContent) { case JustifyContent.FLEX_START: childTop = paddingTop; childBottom = parentHeight - paddingBottom; break; case JustifyContent.FLEX_END: childTop = parentHeight - flexLine.mMainSize + paddingBottom; childBottom = flexLine.mMainSize - paddingTop; break; case JustifyContent.CENTER: childTop = paddingTop + (parentHeight - flexLine.mMainSize) / 2f; childBottom = parentHeight - paddingBottom - (parentHeight - flexLine.mMainSize) / 2f; break; case JustifyContent.SPACE_AROUND: if (flexLine.mItemCount != 0) { spaceBetweenItem = (parentHeight - flexLine.mMainSize) / (float) flexLine.mItemCount; } childTop = paddingTop + spaceBetweenItem / 2f; childBottom = parentHeight - paddingBottom - spaceBetweenItem / 2f; break; case JustifyContent.SPACE_BETWEEN: childTop = paddingTop; float denominator = flexLine.mItemCount != 1 ? flexLine.mItemCount - 1 : 1f; spaceBetweenItem = (parentHeight - flexLine.mMainSize) / denominator; childBottom = parentHeight - paddingBottom; break; case JustifyContent.SPACE_EVENLY: if (flexLine.mItemCount != 0) { spaceBetweenItem = (parentHeight - flexLine.mMainSize) / (float) (flexLine.mItemCount + 1); } childTop = paddingTop + spaceBetweenItem; childBottom = parentHeight - paddingBottom - spaceBetweenItem; break; default: throw new IllegalStateException("Invalid justifyContent is set: " + mJustifyContent); } childTop -= mAnchorInfo.mPerpendicularCoordinate; childBottom -= mAnchorInfo.mPerpendicularCoordinate; spaceBetweenItem = Math.max(spaceBetweenItem, 0); // Used only when mLayoutDirection == LayoutState.LAYOUT_START to remember the index // a flex item should be inserted int indexInFlexLine = 0; for (int i = startPosition, itemCount = flexLine.getItemCount(); i < startPosition + itemCount; i++) { View view = getFlexItemAt(i); if (view == null) { continue; } // Retrieve the measure spec from the cache because the view may be re-created when // retrieved from Recycler, in that case measured width/height are set to 0 even // each visible child should be measured at least once in the FlexboxHelper long measureSpec = mFlexboxHelper.mMeasureSpecCache[i]; int widthSpec = mFlexboxHelper.extractLowerInt(measureSpec); int heightSpec = mFlexboxHelper.extractHigherInt(measureSpec); LayoutParams lp = (LayoutParams) view.getLayoutParams(); if (shouldMeasureChild(view, widthSpec, heightSpec, lp)) { view.measure(widthSpec, heightSpec); } childTop += (lp.topMargin + getTopDecorationHeight(view)); childBottom -= (lp.rightMargin + getBottomDecorationHeight(view)); if (layoutState.mLayoutDirection == LayoutState.LAYOUT_END) { calculateItemDecorationsForChild(view, TEMP_RECT); addView(view); } else { calculateItemDecorationsForChild(view, TEMP_RECT); addView(view, indexInFlexLine); indexInFlexLine++; } int leftWithDecoration = childLeft + getLeftDecorationWidth(view); int rightWithDecoration = childRight - getRightDecorationWidth(view); if (mIsRtl) { if (mFromBottomToTop) { mFlexboxHelper.layoutSingleChildVertical(view, flexLine, mIsRtl, rightWithDecoration - view.getMeasuredWidth(), Math.round(childBottom) - view.getMeasuredHeight(), rightWithDecoration, Math.round(childBottom)); } else { mFlexboxHelper.layoutSingleChildVertical(view, flexLine, mIsRtl, rightWithDecoration - view.getMeasuredWidth(), Math.round(childTop), rightWithDecoration, Math.round(childTop) + view.getMeasuredHeight()); } } else { if (mFromBottomToTop) { mFlexboxHelper.layoutSingleChildVertical(view, flexLine, mIsRtl, leftWithDecoration, Math.round(childBottom) - view.getMeasuredHeight(), leftWithDecoration + view.getMeasuredWidth(), Math.round(childBottom)); } else { mFlexboxHelper.layoutSingleChildVertical(view, flexLine, mIsRtl, leftWithDecoration, Math.round(childTop), leftWithDecoration + view.getMeasuredWidth(), Math.round(childTop) + view.getMeasuredHeight()); } } childTop += (view.getMeasuredHeight() + lp.topMargin + getBottomDecorationHeight(view) + spaceBetweenItem); childBottom -= (view.getMeasuredHeight() + lp.bottomMargin + getTopDecorationHeight(view) + spaceBetweenItem); } layoutState.mFlexLinePosition += mLayoutState.mLayoutDirection; return flexLine.getCrossSize(); }
From source file:android.support.v7.widget.LinearLayoutCompat.java
/** * Measures the children when the orientation of this LinearLayout is set * to {@link #HORIZONTAL}./*from w w w. j av a 2 s . c om*/ * * @param widthMeasureSpec Horizontal space requirements as imposed by the parent. * @param heightMeasureSpec Vertical space requirements as imposed by the parent. * * @see #getOrientation() * @see #setOrientation(int) * @see #onMeasure(int, int) */ void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) { mTotalLength = 0; int maxHeight = 0; int childState = 0; int alternativeMaxHeight = 0; int weightedMaxHeight = 0; boolean allFillParent = true; float totalWeight = 0; final int count = getVirtualChildCount(); final int widthMode = MeasureSpec.getMode(widthMeasureSpec); final int heightMode = MeasureSpec.getMode(heightMeasureSpec); boolean matchHeight = false; boolean skippedMeasure = false; if (mMaxAscent == null || mMaxDescent == null) { mMaxAscent = new int[VERTICAL_GRAVITY_COUNT]; mMaxDescent = new int[VERTICAL_GRAVITY_COUNT]; } final int[] maxAscent = mMaxAscent; final int[] maxDescent = mMaxDescent; maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1; maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1; final boolean baselineAligned = mBaselineAligned; final boolean useLargestChild = mUseLargestChild; final boolean isExactly = widthMode == MeasureSpec.EXACTLY; int largestChildWidth = Integer.MIN_VALUE; // See how wide everyone is. Also remember max height. for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); if (child == null) { mTotalLength += measureNullChild(i); continue; } if (child.getVisibility() == GONE) { i += getChildrenSkipCount(child, i); continue; } if (hasDividerBeforeChildAt(i)) { mTotalLength += mDividerWidth; } final LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child.getLayoutParams(); totalWeight += lp.weight; if (widthMode == MeasureSpec.EXACTLY && lp.width == 0 && lp.weight > 0) { // Optimization: don't bother measuring children who are going to use // leftover space. These views will get measured again down below if // there is any leftover space. if (isExactly) { mTotalLength += lp.leftMargin + lp.rightMargin; } else { final int totalLength = mTotalLength; mTotalLength = Math.max(totalLength, totalLength + lp.leftMargin + lp.rightMargin); } // Baseline alignment requires to measure widgets to obtain the // baseline offset (in particular for TextViews). The following // defeats the optimization mentioned above. Allow the child to // use as much space as it wants because we can shrink things // later (and re-measure). if (baselineAligned) { final int freeSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); child.measure(freeSpec, freeSpec); } else { skippedMeasure = true; } } else { int oldWidth = Integer.MIN_VALUE; if (lp.width == 0 && lp.weight > 0) { // widthMode is either UNSPECIFIED or AT_MOST, and this // child // wanted to stretch to fill available space. Translate that to // WRAP_CONTENT so that it does not end up with a width of 0 oldWidth = 0; lp.width = LayoutParams.WRAP_CONTENT; } // Determine how big this child would like to be. If this or // previous children have given a weight, then we allow it to // use all available space (and we will shrink things later // if needed). measureChildBeforeLayout(child, i, widthMeasureSpec, totalWeight == 0 ? mTotalLength : 0, heightMeasureSpec, 0); if (oldWidth != Integer.MIN_VALUE) { lp.width = oldWidth; } final int childWidth = child.getMeasuredWidth(); if (isExactly) { mTotalLength += childWidth + lp.leftMargin + lp.rightMargin + getNextLocationOffset(child); } else { final int totalLength = mTotalLength; mTotalLength = Math.max(totalLength, totalLength + childWidth + lp.leftMargin + lp.rightMargin + getNextLocationOffset(child)); } if (useLargestChild) { largestChildWidth = Math.max(childWidth, largestChildWidth); } } boolean matchHeightLocally = false; if (heightMode != MeasureSpec.EXACTLY && lp.height == LayoutParams.MATCH_PARENT) { // The height of the linear layout will scale, and at least one // child said it wanted to match our height. Set a flag indicating that // we need to remeasure at least that view when we know our height. matchHeight = true; matchHeightLocally = true; } final int margin = lp.topMargin + lp.bottomMargin; final int childHeight = child.getMeasuredHeight() + margin; childState = ViewUtils.combineMeasuredStates(childState, ViewCompat.getMeasuredState(child)); if (baselineAligned) { final int childBaseline = child.getBaseline(); if (childBaseline != -1) { // Translates the child's vertical gravity into an index // in the range 0..VERTICAL_GRAVITY_COUNT final int gravity = (lp.gravity < 0 ? mGravity : lp.gravity) & Gravity.VERTICAL_GRAVITY_MASK; final int index = ((gravity >> Gravity.AXIS_Y_SHIFT) & ~Gravity.AXIS_SPECIFIED) >> 1; maxAscent[index] = Math.max(maxAscent[index], childBaseline); maxDescent[index] = Math.max(maxDescent[index], childHeight - childBaseline); } } maxHeight = Math.max(maxHeight, childHeight); allFillParent = allFillParent && lp.height == LayoutParams.MATCH_PARENT; if (lp.weight > 0) { /* * Heights of weighted Views are bogus if we end up * remeasuring, so keep them separate. */ weightedMaxHeight = Math.max(weightedMaxHeight, matchHeightLocally ? margin : childHeight); } else { alternativeMaxHeight = Math.max(alternativeMaxHeight, matchHeightLocally ? margin : childHeight); } i += getChildrenSkipCount(child, i); } if (mTotalLength > 0 && hasDividerBeforeChildAt(count)) { mTotalLength += mDividerWidth; } // Check mMaxAscent[INDEX_TOP] first because it maps to Gravity.TOP, // the most common case if (maxAscent[INDEX_TOP] != -1 || maxAscent[INDEX_CENTER_VERTICAL] != -1 || maxAscent[INDEX_BOTTOM] != -1 || maxAscent[INDEX_FILL] != -1) { final int ascent = Math.max(maxAscent[INDEX_FILL], Math.max(maxAscent[INDEX_CENTER_VERTICAL], Math.max(maxAscent[INDEX_TOP], maxAscent[INDEX_BOTTOM]))); final int descent = Math.max(maxDescent[INDEX_FILL], Math.max(maxDescent[INDEX_CENTER_VERTICAL], Math.max(maxDescent[INDEX_TOP], maxDescent[INDEX_BOTTOM]))); maxHeight = Math.max(maxHeight, ascent + descent); } if (useLargestChild && (widthMode == MeasureSpec.AT_MOST || widthMode == MeasureSpec.UNSPECIFIED)) { mTotalLength = 0; for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); if (child == null) { mTotalLength += measureNullChild(i); continue; } if (child.getVisibility() == GONE) { i += getChildrenSkipCount(child, i); continue; } final LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child .getLayoutParams(); if (isExactly) { mTotalLength += largestChildWidth + lp.leftMargin + lp.rightMargin + getNextLocationOffset(child); } else { final int totalLength = mTotalLength; mTotalLength = Math.max(totalLength, totalLength + largestChildWidth + lp.leftMargin + lp.rightMargin + getNextLocationOffset(child)); } } } // Add in our padding mTotalLength += getPaddingLeft() + getPaddingRight(); int widthSize = mTotalLength; // Check against our minimum width widthSize = Math.max(widthSize, getSuggestedMinimumWidth()); // Reconcile our calculated size with the widthMeasureSpec int widthSizeAndState = ViewCompat.resolveSizeAndState(widthSize, widthMeasureSpec, 0); widthSize = widthSizeAndState & ViewCompat.MEASURED_SIZE_MASK; // Either expand children with weight to take up available space or // shrink them if they extend beyond our current bounds. If we skipped // measurement on any children, we need to measure them now. int delta = widthSize - mTotalLength; if (skippedMeasure || delta != 0 && totalWeight > 0.0f) { float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight; maxAscent[0] = maxAscent[1] = maxAscent[2] = maxAscent[3] = -1; maxDescent[0] = maxDescent[1] = maxDescent[2] = maxDescent[3] = -1; maxHeight = -1; mTotalLength = 0; for (int i = 0; i < count; ++i) { final View child = getVirtualChildAt(i); if (child == null || child.getVisibility() == View.GONE) { continue; } final LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child .getLayoutParams(); float childExtra = lp.weight; if (childExtra > 0) { // Child said it could absorb extra space -- give him his share int share = (int) (childExtra * delta / weightSum); weightSum -= childExtra; delta -= share; final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin, lp.height); // TODO: Use a field like lp.isMeasured to figure out if this // child has been previously measured if ((lp.width != 0) || (widthMode != MeasureSpec.EXACTLY)) { // child was measured once already above ... base new measurement // on stored values int childWidth = child.getMeasuredWidth() + share; if (childWidth < 0) { childWidth = 0; } child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY), childHeightMeasureSpec); } else { // child was skipped in the loop above. Measure for this first time here child.measure(MeasureSpec.makeMeasureSpec(share > 0 ? share : 0, MeasureSpec.EXACTLY), childHeightMeasureSpec); } // Child may now not fit in horizontal dimension. childState = ViewUtils.combineMeasuredStates(childState, ViewCompat.getMeasuredState(child) & ViewCompat.MEASURED_STATE_MASK); } if (isExactly) { mTotalLength += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin + getNextLocationOffset(child); } else { final int totalLength = mTotalLength; mTotalLength = Math.max(totalLength, totalLength + child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin + getNextLocationOffset(child)); } boolean matchHeightLocally = heightMode != MeasureSpec.EXACTLY && lp.height == LayoutParams.MATCH_PARENT; final int margin = lp.topMargin + lp.bottomMargin; int childHeight = child.getMeasuredHeight() + margin; maxHeight = Math.max(maxHeight, childHeight); alternativeMaxHeight = Math.max(alternativeMaxHeight, matchHeightLocally ? margin : childHeight); allFillParent = allFillParent && lp.height == LayoutParams.MATCH_PARENT; if (baselineAligned) { final int childBaseline = child.getBaseline(); if (childBaseline != -1) { // Translates the child's vertical gravity into an index in the range 0..2 final int gravity = (lp.gravity < 0 ? mGravity : lp.gravity) & Gravity.VERTICAL_GRAVITY_MASK; final int index = ((gravity >> Gravity.AXIS_Y_SHIFT) & ~Gravity.AXIS_SPECIFIED) >> 1; maxAscent[index] = Math.max(maxAscent[index], childBaseline); maxDescent[index] = Math.max(maxDescent[index], childHeight - childBaseline); } } } // Add in our padding mTotalLength += getPaddingLeft() + getPaddingRight(); // TODO: Should we update widthSize with the new total length? // Check mMaxAscent[INDEX_TOP] first because it maps to Gravity.TOP, // the most common case if (maxAscent[INDEX_TOP] != -1 || maxAscent[INDEX_CENTER_VERTICAL] != -1 || maxAscent[INDEX_BOTTOM] != -1 || maxAscent[INDEX_FILL] != -1) { final int ascent = Math.max(maxAscent[INDEX_FILL], Math.max(maxAscent[INDEX_CENTER_VERTICAL], Math.max(maxAscent[INDEX_TOP], maxAscent[INDEX_BOTTOM]))); final int descent = Math.max(maxDescent[INDEX_FILL], Math.max(maxDescent[INDEX_CENTER_VERTICAL], Math.max(maxDescent[INDEX_TOP], maxDescent[INDEX_BOTTOM]))); maxHeight = Math.max(maxHeight, ascent + descent); } } else { alternativeMaxHeight = Math.max(alternativeMaxHeight, weightedMaxHeight); // We have no limit, so make all weighted views as wide as the largest child. // Children will have already been measured once. if (useLargestChild && widthMode != MeasureSpec.EXACTLY) { for (int i = 0; i < count; i++) { final View child = getVirtualChildAt(i); if (child == null || child.getVisibility() == View.GONE) { continue; } final LinearLayoutCompat.LayoutParams lp = (LinearLayoutCompat.LayoutParams) child .getLayoutParams(); float childExtra = lp.weight; if (childExtra > 0) { child.measure(MeasureSpec.makeMeasureSpec(largestChildWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY)); } } } } if (!allFillParent && heightMode != MeasureSpec.EXACTLY) { maxHeight = alternativeMaxHeight; } maxHeight += getPaddingTop() + getPaddingBottom(); // Check against our minimum height maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); setMeasuredDimension(widthSizeAndState | (childState & ViewCompat.MEASURED_STATE_MASK), ViewCompat.resolveSizeAndState(maxHeight, heightMeasureSpec, (childState << ViewCompat.MEASURED_HEIGHT_STATE_SHIFT))); if (matchHeight) { forceUniformHeight(count, widthMeasureSpec); } }
From source file:android.support.v7.internal.widget.ActionBarView.java
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int childCount = getChildCount(); if (mIsCollapsable) { int visibleChildren = 0; for (int i = 0; i < childCount; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE && !(child == mMenuView && mMenuView.getChildCount() == 0)) { visibleChildren++;// w w w . ja v a 2s. c om } } if (visibleChildren == 0) { // No size for an empty action bar when collapsable. setMeasuredDimension(0, 0); mIsCollapsed = true; return; } } mIsCollapsed = false; int widthMode = MeasureSpec.getMode(widthMeasureSpec); if (widthMode != MeasureSpec.EXACTLY) { throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + "with android:layout_width=\"MATCH_PARENT\" (or fill_parent)"); } int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (heightMode != MeasureSpec.AT_MOST) { throw new IllegalStateException(getClass().getSimpleName() + " can only be used " + "with android:layout_height=\"wrap_content\""); } int contentWidth = MeasureSpec.getSize(widthMeasureSpec); int maxHeight = mContentHeight > 0 ? mContentHeight : MeasureSpec.getSize(heightMeasureSpec); final int verticalPadding = getPaddingTop() + getPaddingBottom(); final int paddingLeft = getPaddingLeft(); final int paddingRight = getPaddingRight(); final int height = maxHeight - verticalPadding; final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST); int availableWidth = contentWidth - paddingLeft - paddingRight; int leftOfCenter = availableWidth / 2; int rightOfCenter = leftOfCenter; HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout; if (homeLayout.getVisibility() != GONE) { final ViewGroup.LayoutParams lp = homeLayout.getLayoutParams(); int homeWidthSpec; if (lp.width < 0) { homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST); } else { homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY); } homeLayout.measure(homeWidthSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); final int homeWidth = homeLayout.getMeasuredWidth() + homeLayout.getLeftOffset(); availableWidth = Math.max(0, availableWidth - homeWidth); leftOfCenter = Math.max(0, availableWidth - homeWidth); } if (mMenuView != null && mMenuView.getParent() == this) { availableWidth = measureChildView(mMenuView, availableWidth, childSpecHeight, 0); rightOfCenter = Math.max(0, rightOfCenter - mMenuView.getMeasuredWidth()); } if (mIndeterminateProgressView != null && mIndeterminateProgressView.getVisibility() != GONE) { availableWidth = measureChildView(mIndeterminateProgressView, availableWidth, childSpecHeight, 0); rightOfCenter = Math.max(0, rightOfCenter - mIndeterminateProgressView.getMeasuredWidth()); } final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE && (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0; if (mExpandedActionView == null) { switch (mNavigationMode) { case ActionBar.NAVIGATION_MODE_LIST: if (mListNavLayout != null) { final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding; availableWidth = Math.max(0, availableWidth - itemPaddingSize); leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize); mListNavLayout.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); final int listNavWidth = mListNavLayout.getMeasuredWidth(); availableWidth = Math.max(0, availableWidth - listNavWidth); leftOfCenter = Math.max(0, leftOfCenter - listNavWidth); } break; case ActionBar.NAVIGATION_MODE_TABS: if (mTabScrollView != null) { final int itemPaddingSize = showTitle ? mItemPadding * 2 : mItemPadding; availableWidth = Math.max(0, availableWidth - itemPaddingSize); leftOfCenter = Math.max(0, leftOfCenter - itemPaddingSize); mTabScrollView.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); final int tabWidth = mTabScrollView.getMeasuredWidth(); availableWidth = Math.max(0, availableWidth - tabWidth); leftOfCenter = Math.max(0, leftOfCenter - tabWidth); } break; } } View customView = null; if (mExpandedActionView != null) { customView = mExpandedActionView; } else if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) { customView = mCustomNavView; } if (customView != null) { final ViewGroup.LayoutParams lp = generateLayoutParams(customView.getLayoutParams()); final ActionBar.LayoutParams ablp = lp instanceof ActionBar.LayoutParams ? (ActionBar.LayoutParams) lp : null; int horizontalMargin = 0; int verticalMargin = 0; if (ablp != null) { horizontalMargin = ablp.leftMargin + ablp.rightMargin; verticalMargin = ablp.topMargin + ablp.bottomMargin; } // If the action bar is wrapping to its content height, don't allow a custom // view to FILL_PARENT. int customNavHeightMode; if (mContentHeight <= 0) { customNavHeightMode = MeasureSpec.AT_MOST; } else { customNavHeightMode = lp.height != LayoutParams.WRAP_CONTENT ? MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; } final int customNavHeight = Math.max(0, (lp.height >= 0 ? Math.min(lp.height, height) : height) - verticalMargin); final int customNavWidthMode = lp.width != LayoutParams.WRAP_CONTENT ? MeasureSpec.EXACTLY : MeasureSpec.AT_MOST; int customNavWidth = Math.max(0, (lp.width >= 0 ? Math.min(lp.width, availableWidth) : availableWidth) - horizontalMargin); final int hgrav = (ablp != null ? ablp.gravity : DEFAULT_CUSTOM_GRAVITY) & Gravity.HORIZONTAL_GRAVITY_MASK; // Centering a custom view is treated specially; we try to center within the whole // action bar rather than in the available space. if (hgrav == Gravity.CENTER_HORIZONTAL && lp.width == LayoutParams.FILL_PARENT) { customNavWidth = Math.min(leftOfCenter, rightOfCenter) * 2; } customView.measure(MeasureSpec.makeMeasureSpec(customNavWidth, customNavWidthMode), MeasureSpec.makeMeasureSpec(customNavHeight, customNavHeightMode)); availableWidth -= horizontalMargin + customView.getMeasuredWidth(); } if (mExpandedActionView == null && showTitle) { availableWidth = measureChildView(mTitleLayout, availableWidth, MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.EXACTLY), 0); leftOfCenter = Math.max(0, leftOfCenter - mTitleLayout.getMeasuredWidth()); } if (mContentHeight <= 0) { int measuredHeight = 0; for (int i = 0; i < childCount; i++) { View v = getChildAt(i); int paddedViewHeight = v.getMeasuredHeight() + verticalPadding; if (paddedViewHeight > measuredHeight) { measuredHeight = paddedViewHeight; } } setMeasuredDimension(contentWidth, measuredHeight); } else { setMeasuredDimension(contentWidth, maxHeight); } if (mContextView != null) { mContextView.setContentHeight(getMeasuredHeight()); } if (mProgressView != null && mProgressView.getVisibility() != GONE) { mProgressView.measure( MeasureSpec.makeMeasureSpec(contentWidth - mProgressBarPadding * 2, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.AT_MOST)); } }
From source file:com.jecelyin.editor.v2.widget.AnyDrawerLayout.java
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) { if (isInEditMode()) { // Don't crash the layout editor. Consume all of the space if specified // or pick a magic number from thin air otherwise. // TODO Better communication with tools of this bogus state. // It will crash on a real device. if (widthMode == MeasureSpec.AT_MOST) { widthMode = MeasureSpec.EXACTLY; } else if (widthMode == MeasureSpec.UNSPECIFIED) { widthMode = MeasureSpec.EXACTLY; widthSize = 300;// ww w. java 2 s .c o m } if (heightMode == MeasureSpec.AT_MOST) { heightMode = MeasureSpec.EXACTLY; } else if (heightMode == MeasureSpec.UNSPECIFIED) { heightMode = MeasureSpec.EXACTLY; heightSize = 300; } } else { throw new IllegalArgumentException("DrawerLayout must be measured with MeasureSpec.EXACTLY."); } } setMeasuredDimension(widthSize, heightSize); final boolean applyInsets = mLastInsets != null && ViewCompat.getFitsSystemWindows(this); final int layoutDirection = ViewCompat.getLayoutDirection(this); // Only one drawer is permitted along each vertical edge (left / right). These two booleans // are tracking the presence of the edge drawers. boolean hasDrawerOnLeftEdge = false; boolean hasDrawerOnRightEdge = false; boolean hasDrawerOnBottomEdge = false; final int childCount = getChildCount(); for (int i = 0; i < childCount; i++) { final View child = getChildAt(i); if (child.getVisibility() == GONE) { continue; } final @EdgeGravity int vchildGravity = getDrawerViewAbsoluteGravity(child) & Gravity.VERTICAL_GRAVITY_MASK; boolean isBottomEdgeDrawer = (vchildGravity == Gravity.BOTTOM); final LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (applyInsets && !isBottomEdgeDrawer) { final int cgrav = GravityCompat.getAbsoluteGravity(lp.gravity, layoutDirection); if (ViewCompat.getFitsSystemWindows(child)) { IMPL.dispatchChildInsets(child, mLastInsets, cgrav); } else { IMPL.applyMarginInsets(lp, mLastInsets, cgrav); } } if (isContentView(child)) { // Content views get measured at exactly the layout's size. final int contentWidthSpec = MeasureSpec.makeMeasureSpec(widthSize - lp.leftMargin - lp.rightMargin, MeasureSpec.EXACTLY); final int contentHeightSpec = MeasureSpec .makeMeasureSpec(heightSize - lp.topMargin - lp.bottomMargin, MeasureSpec.EXACTLY); child.measure(contentWidthSpec, contentHeightSpec); } else if (isDrawerView(child)) { if (SET_DRAWER_SHADOW_FROM_ELEVATION) { if (ViewCompat.getElevation(child) != mDrawerElevation) { ViewCompat.setElevation(child, mDrawerElevation); } } final @EdgeGravity int childGravity = getDrawerViewAbsoluteGravity(child) & Gravity.HORIZONTAL_GRAVITY_MASK; // final @EdgeGravity int vchildGravity = // getDrawerViewAbsoluteGravity(child) & Gravity.VERTICAL_GRAVITY_MASK; // Note that the isDrawerView check guarantees that childGravity here is either // LEFT or RIGHT boolean isLeftEdgeDrawer = (childGravity == Gravity.LEFT); if ((isLeftEdgeDrawer && hasDrawerOnLeftEdge) || (isBottomEdgeDrawer && hasDrawerOnBottomEdge) || (!isBottomEdgeDrawer && !isLeftEdgeDrawer && hasDrawerOnRightEdge)) { throw new IllegalStateException("Child drawer has absolute gravity " + gravityToString(isBottomEdgeDrawer ? vchildGravity : childGravity) + " but this " + TAG + " already has a " + "drawer view along that edge"); } if (isBottomEdgeDrawer) { hasDrawerOnBottomEdge = true; } else if (isLeftEdgeDrawer) { hasDrawerOnLeftEdge = true; } else { hasDrawerOnRightEdge = true; } // View ??? int minDrawerMargin = isBottomEdgeDrawer ? 0 : mMinDrawerMargin; final int drawerWidthSpec = getChildMeasureSpec(widthMeasureSpec, minDrawerMargin + lp.leftMargin + lp.rightMargin, lp.width); final int drawerHeightSpec = getChildMeasureSpec(heightMeasureSpec, lp.topMargin + lp.bottomMargin, lp.height); child.measure(drawerWidthSpec, drawerHeightSpec); } else { throw new IllegalStateException("Child " + child + " at index " + i + " does not have a valid layout_gravity - must be Gravity.LEFT, " + "Gravity.RIGHT, Gravity.BOTTOM or Gravity.NO_GRAVITY"); } } }