List of usage examples for android.view View getMeasuredHeight
public final int getMeasuredHeight()
From source file:com.aliasapps.seq.scroller.TwoWayView.java
/** * Measures the width of the given range of children (inclusive) and * returns the width with this TwoWayView's padding and item margin widths * included. If maxWidth is provided, the measuring will stop when the * current width reaches maxWidth.//from w w w .j av a 2 s. co m * * @param heightMeasureSpec The height measure spec to be given to a child's * {@link View#measure(int, int)}. * @param startPosition The position of the first child to be shown. * @param endPosition The (inclusive) position of the last child to be * shown. Specify {@link #NO_POSITION} if the last child should be * the last available child from the adapter. * @param maxWidth The maximum width that will be returned (if all the * children don't fit in this value, this value will be * returned). * @param disallowPartialChildPosition In general, whether the returned * width should only contain entire children. This is more * powerful--it is the first inclusive position at which partial * children will not be allowed. Example: it looks nice to have * at least 3 completely visible children, and in portrait this * will most likely fit; but in landscape there could be times * when even 2 children can not be completely shown, so a value * of 2 (remember, inclusive) would be good (assuming * startPosition is 0). * @return The width of this TwoWayView with the given children. */ private int measureWidthOfChildren(int heightMeasureSpec, int startPosition, int endPosition, final int maxWidth, int disallowPartialChildPosition) { final int paddingLeft = getPaddingLeft(); final int paddingRight = getPaddingRight(); final ListAdapter adapter = mAdapter; if (adapter == null) { return paddingLeft + paddingRight; } // Include the padding of the list int returnedWidth = paddingLeft + paddingRight; final int itemMargin = mItemMargin; // The previous height value that was less than maxHeight and contained // no partial children int prevWidthWithoutPartialChild = 0; int i; View child; // mItemCount - 1 since endPosition parameter is inclusive endPosition = (endPosition == NO_POSITION) ? adapter.getCount() - 1 : endPosition; final RecycleBin recycleBin = mRecycler; final boolean shouldRecycle = recycleOnMeasure(); final boolean[] isScrap = mIsScrap; for (i = startPosition; i <= endPosition; ++i) { child = obtainView(i, isScrap); measureScrapChild(child, i, heightMeasureSpec); if (i > 0) { // Count the item margin for all but one child returnedWidth += itemMargin; } // Recycle the view before we possibly return from the method if (shouldRecycle) { recycleBin.addScrapView(child, -1); } returnedWidth += child.getMeasuredHeight(); if (returnedWidth >= maxWidth) { // We went over, figure out which width to return. If returnedWidth > maxWidth, // then the i'th position did not fit completely. return (disallowPartialChildPosition >= 0) // Disallowing is enabled (> -1) && (i > disallowPartialChildPosition) // We've past the min pos && (prevWidthWithoutPartialChild > 0) // We have a prev width && (returnedWidth != maxWidth) // i'th child did not fit completely ? prevWidthWithoutPartialChild : maxWidth; } if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) { prevWidthWithoutPartialChild = returnedWidth; } } // At this point, we went through the range of children, and they each // completely fit, so return the returnedWidth return returnedWidth; }
From source file:com.aliasapps.seq.scroller.TwoWayView.java
/** * Measures the height of the given range of children (inclusive) and * returns the height with this TwoWayView's padding and item margin heights * included. If maxHeight is provided, the measuring will stop when the * current height reaches maxHeight./*from w w w .ja v a 2 s.c om*/ * * @param widthMeasureSpec The width measure spec to be given to a child's * {@link View#measure(int, int)}. * @param startPosition The position of the first child to be shown. * @param endPosition The (inclusive) position of the last child to be * shown. Specify {@link #NO_POSITION} if the last child should be * the last available child from the adapter. * @param maxHeight The maximum height that will be returned (if all the * children don't fit in this value, this value will be * returned). * @param disallowPartialChildPosition In general, whether the returned * height should only contain entire children. This is more * powerful--it is the first inclusive position at which partial * children will not be allowed. Example: it looks nice to have * at least 3 completely visible children, and in portrait this * will most likely fit; but in landscape there could be times * when even 2 children can not be completely shown, so a value * of 2 (remember, inclusive) would be good (assuming * startPosition is 0). * @return The height of this TwoWayView with the given children. */ private int measureHeightOfChildren(int widthMeasureSpec, int startPosition, int endPosition, final int maxHeight, int disallowPartialChildPosition) { final int paddingTop = getPaddingTop(); final int paddingBottom = getPaddingBottom(); final ListAdapter adapter = mAdapter; if (adapter == null) { return paddingTop + paddingBottom; } // Include the padding of the list int returnedHeight = paddingTop + paddingBottom; final int itemMargin = mItemMargin; // The previous height value that was less than maxHeight and contained // no partial children int prevHeightWithoutPartialChild = 0; int i; View child; // mItemCount - 1 since endPosition parameter is inclusive endPosition = (endPosition == NO_POSITION) ? adapter.getCount() - 1 : endPosition; final RecycleBin recycleBin = mRecycler; final boolean shouldRecycle = recycleOnMeasure(); final boolean[] isScrap = mIsScrap; for (i = startPosition; i <= endPosition; ++i) { child = obtainView(i, isScrap); measureScrapChild(child, i, widthMeasureSpec); if (i > 0) { // Count the item margin for all but one child returnedHeight += itemMargin; } // Recycle the view before we possibly return from the method if (shouldRecycle) { recycleBin.addScrapView(child, -1); } returnedHeight += child.getMeasuredHeight(); if (returnedHeight >= maxHeight) { // We went over, figure out which height to return. If returnedHeight > maxHeight, // then the i'th position did not fit completely. return (disallowPartialChildPosition >= 0) // Disallowing is enabled (> -1) && (i > disallowPartialChildPosition) // We've past the min pos && (prevHeightWithoutPartialChild > 0) // We have a prev height && (returnedHeight != maxHeight) // i'th child did not fit completely ? prevHeightWithoutPartialChild : maxHeight; } if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) { prevHeightWithoutPartialChild = returnedHeight; } } // At this point, we went through the range of children, and they each // completely fit, so return the returnedHeight return returnedHeight; }
From source file:com.artifex.mupdf.view.ThumbnailViews.java
/** * Measures the width of the given range of children (inclusive) and returns * the width with this TwoWayView's padding and item margin widths included. * If maxWidth is provided, the measuring will stop when the current width * reaches maxWidth./* w w w . j ava 2s . co m*/ * * @param heightMeasureSpec * The height measure spec to be given to a child's * {@link View#measure(int, int)}. * @param startPosition * The position of the first child to be shown. * @param endPosition * The (inclusive) position of the last child to be shown. * Specify {@link #NO_POSITION} if the last child should be the * last available child from the adapter. * @param maxWidth * The maximum width that will be returned (if all the children * don't fit in this value, this value will be returned). * @param disallowPartialChildPosition * In general, whether the returned width should only contain * entire children. This is more powerful--it is the first * inclusive position at which partial children will not be * allowed. Example: it looks nice to have at least 3 completely * visible children, and in portrait this will most likely fit; * but in landscape there could be times when even 2 children can * not be completely shown, so a value of 2 (remember, inclusive) * would be good (assuming startPosition is 0). * @return The width of this TwoWayView with the given children. */ private int measureWidthOfChildren(int heightMeasureSpec, int startPosition, int endPosition, final int maxWidth, int disallowPartialChildPosition) { final int paddingLeft = getPaddingLeft(); final int paddingRight = getPaddingRight(); final ListAdapter adapter = mAdapter; if (adapter == null) { return paddingLeft + paddingRight; } // Include the padding of the list int returnedWidth = paddingLeft + paddingRight; final int itemMargin = mItemMargin; // The previous height value that was less than maxHeight and contained // no partial children int prevWidthWithoutPartialChild = 0; int i; View child; // mItemCount - 1 since endPosition parameter is inclusive endPosition = (endPosition == NO_POSITION) ? adapter.getCount() - 1 : endPosition; final RecycleBin recycleBin = mRecycler; final boolean shouldRecycle = recycleOnMeasure(); final boolean[] isScrap = mIsScrap; for (i = startPosition; i <= endPosition; ++i) { child = obtainView(i, isScrap); measureScrapChild(child, i, heightMeasureSpec); if (i > 0) { // Count the item margin for all but one child returnedWidth += itemMargin; } // Recycle the view before we possibly return from the method if (shouldRecycle) { recycleBin.addScrapView(child, -1); } returnedWidth += child.getMeasuredHeight(); if (returnedWidth >= maxWidth) { // We went over, figure out which width to return. If // returnedWidth > maxWidth, // then the i'th position did not fit completely. return (disallowPartialChildPosition >= 0) // Disallowing is // enabled (> -1) && (i > disallowPartialChildPosition) // We've past the // min pos && (prevWidthWithoutPartialChild > 0) // We have a prev // width && (returnedWidth != maxWidth) // i'th child did not fit // completely ? prevWidthWithoutPartialChild : maxWidth; } if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) { prevWidthWithoutPartialChild = returnedWidth; } } // At this point, we went through the range of children, and they each // completely fit, so return the returnedWidth return returnedWidth; }
From source file:com.artifex.mupdf.view.ThumbnailViews.java
/** * Measures the height of the given range of children (inclusive) and * returns the height with this TwoWayView's padding and item margin heights * included. If maxHeight is provided, the measuring will stop when the * current height reaches maxHeight.//from www . ja v a 2 s . c o m * * @param widthMeasureSpec * The width measure spec to be given to a child's * {@link View#measure(int, int)}. * @param startPosition * The position of the first child to be shown. * @param endPosition * The (inclusive) position of the last child to be shown. * Specify {@link #NO_POSITION} if the last child should be the * last available child from the adapter. * @param maxHeight * The maximum height that will be returned (if all the children * don't fit in this value, this value will be returned). * @param disallowPartialChildPosition * In general, whether the returned height should only contain * entire children. This is more powerful--it is the first * inclusive position at which partial children will not be * allowed. Example: it looks nice to have at least 3 completely * visible children, and in portrait this will most likely fit; * but in landscape there could be times when even 2 children can * not be completely shown, so a value of 2 (remember, inclusive) * would be good (assuming startPosition is 0). * @return The height of this TwoWayView with the given children. */ private int measureHeightOfChildren(int widthMeasureSpec, int startPosition, int endPosition, final int maxHeight, int disallowPartialChildPosition) { final int paddingTop = getPaddingTop(); final int paddingBottom = getPaddingBottom(); final ListAdapter adapter = mAdapter; if (adapter == null) { return paddingTop + paddingBottom; } // Include the padding of the list int returnedHeight = paddingTop + paddingBottom; final int itemMargin = mItemMargin; // The previous height value that was less than maxHeight and contained // no partial children int prevHeightWithoutPartialChild = 0; int i; View child; // mItemCount - 1 since endPosition parameter is inclusive endPosition = (endPosition == NO_POSITION) ? adapter.getCount() - 1 : endPosition; final RecycleBin recycleBin = mRecycler; final boolean shouldRecycle = recycleOnMeasure(); final boolean[] isScrap = mIsScrap; for (i = startPosition; i <= endPosition; ++i) { child = obtainView(i, isScrap); measureScrapChild(child, i, widthMeasureSpec); if (i > 0) { // Count the item margin for all but one child returnedHeight += itemMargin; } // Recycle the view before we possibly return from the method if (shouldRecycle) { recycleBin.addScrapView(child, -1); } returnedHeight += child.getMeasuredHeight(); if (returnedHeight >= maxHeight) { // We went over, figure out which height to return. If // returnedHeight > maxHeight, // then the i'th position did not fit completely. return (disallowPartialChildPosition >= 0) // Disallowing is // enabled (> -1) && (i > disallowPartialChildPosition) // We've past the // min pos && (prevHeightWithoutPartialChild > 0) // We have a prev // height && (returnedHeight != maxHeight) // i'th child did not // fit completely ? prevHeightWithoutPartialChild : maxHeight; } if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) { prevHeightWithoutPartialChild = returnedHeight; } } // At this point, we went through the range of children, and they each // completely fit, so return the returnedHeight return returnedHeight; }
From source file:com.aliasapps.seq.scroller.TwoWayView.java
@TargetApi(11) private void setupChild(View child, int position, int top, int left, boolean flow, boolean selected, boolean recycled) { final boolean isSelected = selected && shouldShowSelector(); final boolean updateChildSelected = isSelected != child.isSelected(); final int touchMode = mTouchMode; final boolean isPressed = touchMode > TOUCH_MODE_DOWN && touchMode < TOUCH_MODE_DRAGGING && mMotionPosition == position; final boolean updateChildPressed = isPressed != child.isPressed(); final boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested(); // Respect layout params that are already in the view. Otherwise make some up... LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp == null) { lp = generateDefaultLayoutParams(); }//from www . j a v a2s . c om lp.viewType = mAdapter.getItemViewType(position); if (recycled && !lp.forceAdd) { attachViewToParent(child, (flow ? -1 : 0), lp); } else { lp.forceAdd = false; addViewInLayout(child, (flow ? -1 : 0), lp, true); } if (updateChildSelected) { child.setSelected(isSelected); } if (updateChildPressed) { child.setPressed(isPressed); } if (mChoiceMode.compareTo(ChoiceMode.NONE) != 0 && mCheckStates != null) { if (child instanceof Checkable) { ((Checkable) child).setChecked(mCheckStates.get(position)); } else if (getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) { child.setActivated(mCheckStates.get(position)); } } if (needToMeasure) { measureChild(child, lp); } else { cleanupLayoutState(child); } final int w = child.getMeasuredWidth(); final int h = child.getMeasuredHeight(); final int childTop = (mIsVertical && !flow ? top - h : top); final int childLeft = (!mIsVertical && !flow ? left - w : left); if (needToMeasure) { final int childRight = childLeft + w; final int childBottom = childTop + h; child.layout(childLeft, childTop, childRight, childBottom); } else { child.offsetLeftAndRight(childLeft - child.getLeft()); child.offsetTopAndBottom(childTop - child.getTop()); } }
From source file:com.artifex.mupdf.view.ThumbnailViews.java
@TargetApi(11) private void setupChild(View child, int position, int top, int left, boolean flow, boolean selected, boolean recycled) { final boolean isSelected = selected && shouldShowSelector(); final boolean updateChildSelected = isSelected != child.isSelected(); final int touchMode = mTouchMode; final boolean isPressed = touchMode > TOUCH_MODE_DOWN && touchMode < TOUCH_MODE_DRAGGING && mMotionPosition == position; final boolean updateChildPressed = isPressed != child.isPressed(); final boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested(); // Respect layout params that are already in the view. Otherwise make // some up... LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp == null) { lp = generateDefaultLayoutParams(); }//w ww . ja v a 2 s. co m lp.viewType = mAdapter.getItemViewType(position); if (recycled && !lp.forceAdd) { attachViewToParent(child, (flow ? -1 : 0), lp); } else { lp.forceAdd = false; addViewInLayout(child, (flow ? -1 : 0), lp, true); } if (updateChildSelected) { child.setSelected(isSelected); } if (updateChildPressed) { child.setPressed(isPressed); } if (mChoiceMode.compareTo(ChoiceMode.NONE) != 0 && mCheckStates != null) { if (child instanceof Checkable) { ((Checkable) child).setChecked(mCheckStates.get(position)); } else if (getContext().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) { child.setActivated(mCheckStates.get(position)); } } if (needToMeasure) { measureChild(child, lp); } else { cleanupLayoutState(child); } final int w = child.getMeasuredWidth(); final int h = child.getMeasuredHeight(); final int childTop = (mIsVertical && !flow ? top - h : top); final int childLeft = (!mIsVertical && !flow ? left - w : left); if (needToMeasure) { final int childRight = childLeft + w; final int childBottom = childTop + h; child.layout(childLeft, childTop, childRight, childBottom); } else { child.offsetLeftAndRight(childLeft - child.getLeft()); child.offsetTopAndBottom(childTop - child.getTop()); } }
From source file:com.artifex.mupdflib.TwoWayView.java
@TargetApi(11) private void setupChild(View child, int position, int top, int left, boolean flow, boolean selected, boolean recycled) { final boolean isSelected = selected && shouldShowSelector(); final boolean updateChildSelected = isSelected != child.isSelected(); final int touchMode = mTouchMode; final boolean isPressed = touchMode > TOUCH_MODE_DOWN && touchMode < TOUCH_MODE_DRAGGING && mMotionPosition == position; final boolean updateChildPressed = isPressed != child.isPressed(); final boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested(); // Respect layout params that are already in the view. Otherwise make some up... LayoutParams lp = (LayoutParams) child.getLayoutParams(); if (lp == null) { lp = generateDefaultLayoutParams(); }// w w w.j av a2s . c o m lp.viewType = mAdapter.getItemViewType(position); if (recycled && !lp.forceAdd) { attachViewToParent(child, (flow ? -1 : 0), lp); } else { lp.forceAdd = false; addViewInLayout(child, (flow ? -1 : 0), lp, true); } if (updateChildSelected) { child.setSelected(isSelected); } if (updateChildPressed) { child.setPressed(isPressed); } if (mChoiceMode != ChoiceMode.NONE && mCheckStates != null) { if (child instanceof Checkable) { ((Checkable) child).setChecked(mCheckStates.get(position)); } else if (Build.VERSION.SDK_INT >= HONEYCOMB) { child.setActivated(mCheckStates.get(position)); } } if (needToMeasure) { measureChild(child, lp); } else { cleanupLayoutState(child); } final int w = child.getMeasuredWidth(); final int h = child.getMeasuredHeight(); final int childTop = (mIsVertical && !flow ? top - h : top); final int childLeft = (!mIsVertical && !flow ? left - w : left); if (needToMeasure) { final int childRight = childLeft + w; final int childBottom = childTop + h; child.layout(childLeft, childTop, childRight, childBottom); } else { child.offsetLeftAndRight(childLeft - child.getLeft()); child.offsetTopAndBottom(childTop - child.getTop()); } }
From source file:app.umitems.greenclock.widget.sgv.StaggeredGridView.java
/** * Measure and layout all currently visible children. * * @param queryAdapter true to requery the adapter for view data *//*from w ww . j a v a 2s .c o m*/ final void layoutChildren(boolean queryAdapter) { final int paddingLeft = getPaddingLeft(); final int paddingRight = getPaddingRight(); final int itemMargin = mItemMargin; final int availableWidth = (getWidth() - paddingLeft - paddingRight - itemMargin * (mColCount - 1)); final int colWidth = availableWidth / mColCount; // The availableWidth may not be divisible by mColCount. Keep the // remainder. It will be added to the width of the last view in the row. final int remainder = availableWidth % mColCount; boolean viewsRemovedInLayout = false; // If we're animating out stale views, then we want to defer recycling of views. final boolean deferRecyclingForAnimation = mAnimationOutMode != AnimationOut.NONE; if (!deferRecyclingForAnimation) { final int childCount = getChildCount(); // If the latest data set has fewer data items than mFirstPosition, don't keep any // views on screen, and just let the layout logic below retrieve appropriate views // from the recycler. final int viewsToKeepOnScreen = (mItemCount <= mFirstPosition) ? 0 : mItemCount - mFirstPosition; if (childCount > viewsToKeepOnScreen) { // If there are more views laid out than the number of data items remaining to be // laid out, recycle the extraneous views. recycleViewsInRange(viewsToKeepOnScreen, childCount - 1); viewsRemovedInLayout = true; } } else { mViewsToAnimateOut.clear(); } for (int i = 0; i < getChildCount(); i++) { final int position = mFirstPosition + i; View child = getChildAt(i); final int highestAvailableLayoutPosition = mItemBottoms[getNextColumnDown()]; if (deferRecyclingForAnimation && (position >= mItemCount || highestAvailableLayoutPosition >= getHeight())) { // For the remainder of views on screen, they should not be on screen, so we can // skip layout. Add them to the list of views to animate out. // We should only get in this position if deferRecyclingForAnimation = true, // otherwise, we should've recycled all views before getting into this layout loop. mViewsToAnimateOut.add(child); continue; } LayoutParams lp = null; int col = -1; if (child != null) { lp = (LayoutParams) child.getLayoutParams(); col = lp.column; } final boolean needsLayout = queryAdapter || child == null || child.isLayoutRequested(); if (queryAdapter) { View newView = null; if (deferRecyclingForAnimation) { // If we are deferring recycling for animation, then we don't want to pass the // current child in to obtainView for re-use. obtainView() in this case should // try to find the view belonging to this item on screen, or populate a fresh // one from the recycler. newView = obtainView(position); } else { newView = obtainView(position, child); } // Update layout params since they may have changed lp = (LayoutParams) newView.getLayoutParams(); if (newView != child) { if (child != null && !deferRecyclingForAnimation) { mRecycler.addScrap(child); removeViewInLayout(child); viewsRemovedInLayout = true; } // If this view is already in the layout hierarchy, we can just detach it // from the parent and re-attach it at the correct index. If the view has // already been removed from the layout hierarchy, getParent() == null. if (newView.getParent() == this) { detachViewFromParent(newView); attachViewToParent(newView, i, lp); } else { addViewInLayout(newView, i, lp); } } child = newView; // Since the data has changed, we need to make sure the next child is in the // right column. We choose the next column down (vs. next column up) because we // are filling from the top of the screen downwards as we iterate through // visible children. (We take span into account below.) lp.column = getNextColumnDown(); col = lp.column; } setReorderingArea(lp); final int span = Math.min(mColCount, lp.span); // Given the span, check if there's enough space to put this view at this column. // IMPORTANT Propagate the same logic to {@link #calculateLayoutStartOffsets}. if (span > 1) { if (mIsRtlLayout) { // For RTL layout, if the current column index is less than the span of the // child, then we know that there is not enough room remaining to lay this // child out (e.g., if col == 0, but span == 2, then laying this child down // at column = col would put us out of bound into a negative column index.). // For this scenario, reset the index back to the right-most column, and lay // out the child at this position where we can ensure that we can display as // much of the child as possible. if (col + 1 < span) { col = mColCount - 1; } } else { if (mColCount - col < span) { // If not, reset the col to 0. col = 0; } } lp.column = col; } int widthSize = (colWidth * span + itemMargin * (span - 1)); // If it is rtl, we layout the view from col to col - span + // 1. If it reaches the most left column, i.e. we added the // additional width. So the check it span == col +1 if ((mIsRtlLayout && span == col + 1) || (!mIsRtlLayout && span + col == mColCount)) { widthSize += remainder; } if (needsLayout) { final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); final int heightSpec; if (lp.height == LayoutParams.WRAP_CONTENT) { heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } else { heightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY); } child.measure(widthSpec, heightSpec); } // Place the top of this child beneath the last by finding the lowest coordinate across // the columns that this child will span. For LTR layout, we scan across from left to // right, and for RTL layout, we scan from right to left. // TODO: Consolidate this logic with getNextRecordDown() in the future, as that method // already calculates the margins for us. This will keep the implementation consistent // with fillUp() and fillDown(). int childTop = mItemBottoms[col] + mItemMargin; if (span > 1) { int lowest = childTop; for (int spanIndex = 0; spanIndex < span; spanIndex++) { final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex; final int bottom = mItemBottoms[index] + mItemMargin; if (bottom > lowest) { lowest = bottom; } } childTop = lowest; } final int childHeight = child.getMeasuredHeight(); final int childBottom = childTop + childHeight; int childLeft = 0; int childRight = 0; if (mIsRtlLayout) { childRight = (getWidth() - paddingRight) - (mColCount - col - 1) * (colWidth + itemMargin); childLeft = childRight - child.getMeasuredWidth(); } else { childLeft = paddingLeft + col * (colWidth + itemMargin); childRight = childLeft + child.getMeasuredWidth(); } /* Log.v(TAG, "[layoutChildren] height: " + childHeight + " top: " + childTop + " bottom: " + childBottom + " left: " + childLeft + " column: " + col + " position: " + position + " id: " + lp.id); */ child.layout(childLeft, childTop, childRight, childBottom); if (lp.id == mFocusedChildIdToScrollIntoView) { child.requestFocus(); } for (int spanIndex = 0; spanIndex < span; spanIndex++) { final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex; mItemBottoms[index] = childBottom; } // Whether or not LayoutRecords may have already existed for the view at this position // on screen, we'll update it after we lay out to ensure that the LayoutRecord // has the most updated information about the view at this position. We can be assured // that all views before those on screen (views with adapter position < mFirstPosition) // have the correct LayoutRecords because calculateLayoutStartOffsets() would have // set them appropriately. LayoutRecord rec = mLayoutRecords.get(position); if (rec == null) { rec = new LayoutRecord(); mLayoutRecords.put(position, rec); } rec.column = lp.column; rec.height = childHeight; rec.id = lp.id; rec.span = span; } // It appears that removeViewInLayout() does not invalidate. So if we make use of this // method during layout, we should invalidate explicitly. if (viewsRemovedInLayout || deferRecyclingForAnimation) { invalidate(); } }
From source file:com.deepak.myclock.widget.sgv.StaggeredGridView.java
/** * Measure and layout all currently visible children. * * @param queryAdapter true to requery the adapter for view data *//*from www . ja v a2 s . c o m*/ final void layoutChildren(boolean queryAdapter) { final int paddingLeft = getPaddingLeft(); final int paddingRight = getPaddingRight(); final int itemMargin = mItemMargin; final int availableWidth = (getWidth() - paddingLeft - paddingRight - itemMargin * (mColCount - 1)); final int colWidth = availableWidth / mColCount; // The availableWidth may not be divisible by mColCount. Keep the // remainder. It will be added to the width of the last view in the row. final int remainder = availableWidth % mColCount; boolean viewsRemovedInLayout = false; // If we're animating out stale views, then we want to defer recycling of views. final boolean deferRecyclingForAnimation = mAnimationOutMode != SgvAnimationHelper.AnimationOut.NONE; if (!deferRecyclingForAnimation) { final int childCount = getChildCount(); // If the latest data set has fewer data items than mFirstPosition, don't keep any // views on screen, and just let the layout logic below retrieve appropriate views // from the recycler. final int viewsToKeepOnScreen = (mItemCount <= mFirstPosition) ? 0 : mItemCount - mFirstPosition; if (childCount > viewsToKeepOnScreen) { // If there are more views laid out than the number of data items remaining to be // laid out, recycle the extraneous views. recycleViewsInRange(viewsToKeepOnScreen, childCount - 1); viewsRemovedInLayout = true; } } else { mViewsToAnimateOut.clear(); } for (int i = 0; i < getChildCount(); i++) { final int position = mFirstPosition + i; View child = getChildAt(i); final int highestAvailableLayoutPosition = mItemBottoms[getNextColumnDown()]; if (deferRecyclingForAnimation && (position >= mItemCount || highestAvailableLayoutPosition >= getHeight())) { // For the remainder of views on screen, they should not be on screen, so we can // skip layout. Add them to the list of views to animate out. // We should only get in this position if deferRecyclingForAnimation = true, // otherwise, we should've recycled all views before getting into this layout loop. mViewsToAnimateOut.add(child); continue; } LayoutParams lp = null; int col = -1; if (child != null) { lp = (LayoutParams) child.getLayoutParams(); col = lp.column; } final boolean needsLayout = queryAdapter || child == null || child.isLayoutRequested(); if (queryAdapter) { View newView = null; if (deferRecyclingForAnimation) { // If we are deferring recycling for animation, then we don't want to pass the // current child in to obtainView for re-use. obtainView() in this case should // try to find the view belonging to this item on screen, or populate a fresh // one from the recycler. newView = obtainView(position); } else { newView = obtainView(position, child); } // Update layout params since they may have changed lp = (LayoutParams) newView.getLayoutParams(); if (newView != child) { if (child != null && !deferRecyclingForAnimation) { mRecycler.addScrap(child); removeViewInLayout(child); viewsRemovedInLayout = true; } // If this view is already in the layout hierarchy, we can just detach it // from the parent and re-attach it at the correct index. If the view has // already been removed from the layout hierarchy, getParent() == null. if (newView.getParent() == this) { detachViewFromParent(newView); attachViewToParent(newView, i, lp); } else { addViewInLayout(newView, i, lp); } } child = newView; // Since the data has changed, we need to make sure the next child is in the // right column. We choose the next column down (vs. next column up) because we // are filling from the top of the screen downwards as we iterate through // visible children. (We take span into account below.) lp.column = getNextColumnDown(); col = lp.column; } setReorderingArea(lp); final int span = Math.min(mColCount, lp.span); // Given the span, check if there's enough space to put this view at this column. // IMPORTANT Propagate the same logic to {@link #calculateLayoutStartOffsets}. if (span > 1) { if (mIsRtlLayout) { // For RTL layout, if the current column index is less than the span of the // child, then we know that there is not enough room remaining to lay this // child out (e.g., if col == 0, but span == 2, then laying this child down // at column = col would put us out of bound into a negative column index.). // For this scenario, reset the index back to the right-most column, and lay // out the child at this position where we can ensure that we can display as // much of the child as possible. if (col + 1 < span) { col = mColCount - 1; } } else { if (mColCount - col < span) { // If not, reset the col to 0. col = 0; } } lp.column = col; } int widthSize = (colWidth * span + itemMargin * (span - 1)); // If it is rtl, we layout the view from col to col - span + // 1. If it reaches the most left column, i.e. we added the // additional width. So the check it span == col +1 if ((mIsRtlLayout && span == col + 1) || (!mIsRtlLayout && span + col == mColCount)) { widthSize += remainder; } if (needsLayout) { final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); final int heightSpec; if (lp.height == LayoutParams.WRAP_CONTENT) { heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } else { heightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY); } child.measure(widthSpec, heightSpec); } // Place the top of this child beneath the last by finding the lowest coordinate across // the columns that this child will span. For LTR layout, we scan across from left to // right, and for RTL layout, we scan from right to left. // TODO: Consolidate this logic with getNextRecordDown() in the future, as that method // already calculates the margins for us. This will keep the implementation consistent // with fillUp() and fillDown(). int childTop = mItemBottoms[col] + mItemMargin; if (span > 1) { int lowest = childTop; for (int spanIndex = 0; spanIndex < span; spanIndex++) { final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex; final int bottom = mItemBottoms[index] + mItemMargin; if (bottom > lowest) { lowest = bottom; } } childTop = lowest; } final int childHeight = child.getMeasuredHeight(); final int childBottom = childTop + childHeight; int childLeft = 0; int childRight = 0; if (mIsRtlLayout) { childRight = (getWidth() - paddingRight) - (mColCount - col - 1) * (colWidth + itemMargin); childLeft = childRight - child.getMeasuredWidth(); } else { childLeft = paddingLeft + col * (colWidth + itemMargin); childRight = childLeft + child.getMeasuredWidth(); } /* Log.v(TAG, "[layoutChildren] height: " + childHeight + " top: " + childTop + " bottom: " + childBottom + " left: " + childLeft + " column: " + col + " position: " + position + " id: " + lp.id); */ child.layout(childLeft, childTop, childRight, childBottom); if (lp.id == mFocusedChildIdToScrollIntoView) { child.requestFocus(); } for (int spanIndex = 0; spanIndex < span; spanIndex++) { final int index = mIsRtlLayout ? col - spanIndex : col + spanIndex; mItemBottoms[index] = childBottom; } // Whether or not LayoutRecords may have already existed for the view at this position // on screen, we'll update it after we lay out to ensure that the LayoutRecord // has the most updated information about the view at this position. We can be assured // that all views before those on screen (views with adapter position < mFirstPosition) // have the correct LayoutRecords because calculateLayoutStartOffsets() would have // set them appropriately. LayoutRecord rec = mLayoutRecords.get(position); if (rec == null) { rec = new LayoutRecord(); mLayoutRecords.put(position, rec); } rec.column = lp.column; rec.height = childHeight; rec.id = lp.id; rec.span = span; } // It appears that removeViewInLayout() does not invalidate. So if we make use of this // method during layout, we should invalidate explicitly. if (viewsRemovedInLayout || deferRecyclingForAnimation) { invalidate(); } }