下面列出了android.view.View#forceLayout ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private void measureScrapChild(View child, int position, int widthMeasureSpec, int heightHint) {
LayoutParams p = (LayoutParams) child.getLayoutParams();
if (p == null) {
p = (AbsListView.LayoutParams) generateDefaultLayoutParams();
child.setLayoutParams(p);
}
p.viewType = mAdapter.getItemViewType(position);
p.isEnabled = mAdapter.isEnabled(position);
p.forceAdd = true;
final int childWidthSpec = ViewGroup.getChildMeasureSpec(widthMeasureSpec,
mListPadding.left + mListPadding.right, p.width);
final int lpHeight = p.height;
final int childHeightSpec;
if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeSafeMeasureSpec(heightHint, MeasureSpec.UNSPECIFIED);
}
child.measure(childWidthSpec, childHeightSpec);
// Since this view was measured directly aginst the parent measure
// spec, we must measure it again before reuse.
child.forceLayout();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Position adapterPosition = translatePosition(position);
if (adapterPosition.mPosition == POSITION_HEADER) {
HeaderFillerView v = getHeaderFillerView(adapterPosition.mHeader, convertView, parent);
View view = mDelegate.getHeaderView(adapterPosition.mHeader, (View)v.getTag(), parent);
mGridView.detachHeader((View) v.getTag());
v.setTag(view);
mGridView.attachHeader(view);
convertView = v;
mLastHeaderViewSeen = v;
v.forceLayout();
} else if (adapterPosition.mPosition == POSITION_HEADER_FILLER) {
convertView = getFillerView(convertView, parent, mLastHeaderViewSeen);
convertView.forceLayout();
} else if (adapterPosition.mPosition == POSITION_FILLER) {
convertView = getFillerView(convertView, parent, mLastViewSeen);
} else {
convertView = mDelegate.getView(adapterPosition.mPosition, convertView, parent);
mLastViewSeen = convertView;
}
return convertView;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Position adapterPosition = translatePosition(position);
if (adapterPosition.mPosition == POSITION_HEADER) {
HeaderFillerView v = getHeaderFillerView(adapterPosition.mHeader, convertView, parent);
View view = mDelegate.getHeaderView(adapterPosition.mHeader, (View)v.getTag(), parent);
mGridView.detachHeader((View) v.getTag());
v.setTag(view);
mGridView.attachHeader(view);
convertView = v;
mLastHeaderViewSeen = v;
v.forceLayout();
} else if (adapterPosition.mPosition == POSITION_HEADER_FILLER) {
convertView = getFillerView(convertView, parent, mLastHeaderViewSeen);
convertView.forceLayout();
} else if (adapterPosition.mPosition == POSITION_FILLER) {
convertView = getFillerView(convertView, parent, mLastViewSeen);
} else {
convertView = mDelegate.getView(adapterPosition.mPosition, convertView, parent);
mLastViewSeen = convertView;
}
return convertView;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Position adapterPosition = translatePosition(position);
if (adapterPosition.mPosition == POSITION_HEADER) {
HeaderFillerView v = getHeaderFillerView(adapterPosition.mHeader, convertView, parent);
View view = mDelegate.getHeaderView(adapterPosition.mHeader, (View)v.getTag(), parent);
mGridView.detachHeader((View) v.getTag());
v.setTag(view);
mGridView.attachHeader(view);
convertView = v;
mLastHeaderViewSeen = v;
v.forceLayout();
} else if (adapterPosition.mPosition == POSITION_HEADER_FILLER) {
convertView = getFillerView(convertView, parent, mLastHeaderViewSeen);
convertView.forceLayout();
} else if (adapterPosition.mPosition == POSITION_FILLER) {
convertView = getFillerView(convertView, parent, mLastViewSeen);
} else {
convertView = mDelegate.getView(adapterPosition.mPosition, convertView, parent);
mLastViewSeen = convertView;
}
return convertView;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Position adapterPosition = translatePosition(position);
if (adapterPosition.mPosition == POSITION_HEADER) {
HeaderFillerView v = getHeaderFillerView(adapterPosition.mHeader, convertView, parent);
View view = mDelegate.getHeaderView(adapterPosition.mHeader, (View)v.getTag(), parent);
mGridView.detachHeader((View) v.getTag());
v.setTag(view);
mGridView.attachHeader(view);
convertView = v;
mLastHeaderViewSeen = v;
v.forceLayout();
} else if (adapterPosition.mPosition == POSITION_HEADER_FILLER) {
convertView = getFillerView(convertView, parent, mLastHeaderViewSeen);
convertView.forceLayout();
} else if (adapterPosition.mPosition == POSITION_FILLER) {
convertView = getFillerView(convertView, parent, mLastViewSeen);
} else {
convertView = mDelegate.getView(adapterPosition.mPosition, convertView, parent);
mLastViewSeen = convertView;
}
return convertView;
}
public static void setLeftMargin(@NonNull View view, int margin) {
if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin = margin;
} else {
((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin = margin;
}
view.forceLayout();
view.requestLayout();
}
public static void setRightMargin(@NonNull View view, int margin) {
if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin = margin;
} else {
((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin = margin;
}
view.forceLayout();
view.requestLayout();
}
@Override
protected void onScrollTouchedUp() {
super.onScrollTouchedUp();
int cnt = mItemsLayout.getChildCount();
View itm;
Log.e(LOG_TAG, " ----- layout: " + mItemsLayout.getMeasuredWidth() + mItemsLayout.getMeasuredHeight());
Log.e(LOG_TAG, " -------- dumping " + cnt + " items");
for (int i = 0; i < cnt; i++) {
itm = mItemsLayout.getChildAt(i);
Log.e(LOG_TAG, " item #" + i + ": " + itm.getWidth() + "x" + itm.getHeight());
itm.forceLayout(); // forcing layout without re-rendering parent
}
Log.e(LOG_TAG, " ---------- dumping finished ");
}
@Override
public void onItemsUpdated(RecyclerView recyclerView, int positionStart, int itemCount) {
super.onItemsUpdated(recyclerView, positionStart, itemCount);
mHasDatasetUpdated = true;
for (int i = 0; i < itemCount; ++i) {
View view = findViewByPosition(positionStart + i);
if (view != null) view.forceLayout();
// removeAndRecycleView(view, recyclerView.recyc);
}
}
public static void setLeftMargin(@NonNull View view, int margin) {
if (ViewCompat.getLayoutDirection(view) == ViewCompat.LAYOUT_DIRECTION_LTR) {
((ViewGroup.MarginLayoutParams) view.getLayoutParams()).leftMargin = margin;
} else {
((ViewGroup.MarginLayoutParams) view.getLayoutParams()).rightMargin = margin;
}
view.forceLayout();
view.requestLayout();
}
@Override
protected void onScrollTouchedUp() {
super.onScrollTouchedUp();
int cnt = mItemsLayout.getChildCount();
View itm;
Log.e(LOG_TAG, " ----- layout: " + mItemsLayout.getMeasuredWidth() + mItemsLayout.getMeasuredHeight());
Log.e(LOG_TAG, " -------- dumping " + cnt + " items");
for (int i = 0; i < cnt; i++) {
itm = mItemsLayout.getChildAt(i);
Log.e(LOG_TAG, " item #" + i + ": " + itm.getWidth() + "x" + itm.getHeight());
itm.forceLayout(); // forcing layout without re-rendering parent
}
Log.e(LOG_TAG, " ---------- dumping finished ");
}
synchronized void populate() {
if (mAdapter == null) {
return;
}
// Also, don't populate until we are attached to a window. This is to
// avoid trying to populate before we have restored our view hierarchy
// state and conflicting with what is restored.
if (getWindowToken() == null) {
return;
}
int count = mAdapter.getCount();
Log.d(THIS_FILE, "Populate " + count + " children");
// Compute num of columns
int width = getWidth() - (getPaddingRight() + getPaddingLeft());
int height = getHeight() - (getPaddingTop() + getPaddingBottom());
int cellWidth = width;
int cellHeight = height;
int numRows = 1;
int numColumns = 1;
if(count > 0) {
int possibleColumns = (int) Math.floor( (width * 1.0f)/ (minColumnWidth * 1.0f) );
if(possibleColumns <= 0) {
possibleColumns = 1;
}
numColumns = Math.min(possibleColumns, count);
numRows = count / numColumns;
Log.v(THIS_FILE, "Render a grid of " + numColumns + " x " + numRows);
cellWidth = width / numColumns;
cellHeight = height / numRows;
// TODO : warn - scroll - other?if we are outside bounds with min cell height
if(cellHeight < minRowHeight) {
Log.d(THIS_FILE, "May render weird... min height not correct " + cellHeight);
}
if(cellHeight <= 0 || cellWidth <= 0) {
Log.w(THIS_FILE, "The call grid cannot render " + cellHeight + "x" + cellWidth
+ " for " + width + "x" + height);
cellWidth = minColumnWidth;
cellHeight = minRowHeight;
}
}
// Add it if needed.
int curIndex = -1;
for (curIndex = 0; curIndex < mAdapter.getCount(); curIndex++) {
View ii = null;
if(mItems.size() > curIndex) {
ii = mItems.get(curIndex);
}
ii = mAdapter.getView(curIndex, ii, this);
if(mItems.size() > curIndex) {
mItems.set(curIndex, ii);
}else {
mItems.add(ii);
}
// Set layout of the view
int posX = curIndex % numColumns;
int posY = curIndex / numColumns;
LayoutParams lp = (LayoutParams) ii.getLayoutParams();
if(lp == null) {
lp = new LayoutParams(cellWidth, cellHeight);
}else {
lp.height = cellHeight;
lp.width = cellWidth;
}
lp.leftMargin = posX * cellWidth;
lp.topMargin = posY * cellHeight;
ii.setLayoutParams(lp);
// Append to parent if needed
ViewParent p = ii.getParent();
if(p == null) {
addView(ii);
}else {
if(p == this) {
updateViewLayout(ii, lp);
}else {
Log.w(THIS_FILE, "Call card already attached to somebody else");
}
}
ii.forceLayout();
}
// Remove useles
if(mItems.size() > mAdapter.getCount()) {
for(curIndex = mItems.size()-1; curIndex >= mAdapter.getCount() ; curIndex --) {
removeViewAt(curIndex);
}
}
}
/**
* Measures the height of the given range of children (inclusive) and returns the height
* with this ListView's padding and divider heights included. If maxHeight is provided, the
* measuring will stop when the current height reaches maxHeight.
*
* @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 ListView with the given children.
*/
public int measureHeightOfChildrenCompat(int widthMeasureSpec, int startPosition,
int endPosition, final int maxHeight,
int disallowPartialChildPosition) {
final int paddingTop = getListPaddingTop();
final int paddingBottom = getListPaddingBottom();
final int paddingLeft = getListPaddingLeft();
final int paddingRight = getListPaddingRight();
final int reportedDividerHeight = getDividerHeight();
final Drawable divider = getDivider();
final ListAdapter adapter = getAdapter();
if (adapter == null) {
return paddingTop + paddingBottom;
}
// Include the padding of the list
int returnedHeight = paddingTop + paddingBottom;
final int dividerHeight = ((reportedDividerHeight > 0) && divider != null)
? reportedDividerHeight : 0;
// The previous height value that was less than maxHeight and contained
// no partial children
int prevHeightWithoutPartialChild = 0;
View child = null;
int viewType = 0;
int count = adapter.getCount();
for (int i = 0; i < count; i++) {
int newType = adapter.getItemViewType(i);
if (newType != viewType) {
child = null;
viewType = newType;
}
child = adapter.getView(i, child, this);
// Compute child height spec
int heightMeasureSpec;
ViewGroup.LayoutParams childLp = child.getLayoutParams();
if (childLp == null) {
childLp = generateDefaultLayoutParams();
child.setLayoutParams(childLp);
}
if (childLp.height > 0) {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(childLp.height,
MeasureSpec.EXACTLY);
} else {
heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
child.measure(widthMeasureSpec, heightMeasureSpec);
// Since this view was measured directly aginst the parent measure
// spec, we must measure it again before reuse.
child.forceLayout();
if (i > 0) {
// Count the divider for all but one child
returnedHeight += dividerHeight;
}
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;
}