Back to project page RecyclerViewLib.
The source code is released under:
Apache License
If you think the Android project RecyclerViewLib listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.twotoasters.layoutmanager; /*from ww w. j av a 2 s. c o m*/ import android.content.Context; import android.util.Log; import android.view.View; import com.twotoasters.android.support.v7.widget.RecyclerView; public class GridLayoutManager extends BaseLayoutManager { private static final int DEFAULT_COLUMNS = 2; private int columns; private static final String TAG = GridLayoutManager.class.getSimpleName(); public GridLayoutManager(Context context){ this(context, DEFAULT_COLUMNS, VERTICAL); } public GridLayoutManager(Context context, int columns, int orientation) { super(context, orientation, false); this.columns = columns; } public int getColumns() { return columns; } public void setColumns(int columns) { this.columns = columns; } @Override protected int fill(RecyclerView.Recycler recycler, BaseLayoutManager.RenderState renderState, RecyclerView.State state, boolean stopOnFocusable) { int itemWidth; if (mOrientation == VERTICAL) { itemWidth = (getWidth() - getPaddingLeft() - getPaddingRight()) / columns; }else{ itemWidth = (getHeight() - getPaddingTop() - getPaddingBottom()) / columns; } // max offset we should set is mFastScroll + available final int start = renderState.mAvailable; if (renderState.mScrollingOffset != RenderState.SCOLLING_OFFSET_NaN) { // TODO ugly bug fix. should not happen if (renderState.mAvailable < 0) { renderState.mScrollingOffset += renderState.mAvailable; } recycleByRenderState(recycler, renderState); } int remainingSpace = renderState.mAvailable + renderState.mExtra; int columnCount = 0; while (remainingSpace > 0 && renderState.hasMore(state)) { View view = renderState.next(recycler); if (view == null) { if (DEBUG && renderState.mScrapList == null) { throw new RuntimeException("received null view when unexpected"); } // if we are laying out views in scrap, this may return null which means there is // no more items to layout. break; } RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) view.getLayoutParams(); if (!params.isItemRemoved() && mRenderState.mScrapList == null) { if (mShouldReverseLayout == (renderState.mLayoutDirection == RenderState.LAYOUT_START)) { addView(view); } else { addView(view, 0); } } if (mOrientation == VERTICAL) { params.width = itemWidth - params.leftMargin - params.rightMargin; }else{ params.height = itemWidth - params.topMargin - params.bottomMargin; } measureChildWithMargins(view, 0, 0); int consumed = mOrientationHelper.getDecoratedMeasurement(view); int left, top, right, bottom; if (mOrientation == VERTICAL) { if (isLayoutRTL() == (renderState.mLayoutDirection == RenderState.LAYOUT_END)) { right = getWidth() - getPaddingRight() - itemWidth * columnCount; left = right - mOrientationHelper.getDecoratedMeasurementInOther(view); } else { left = columnCount * itemWidth + getPaddingLeft(); right = left + mOrientationHelper.getDecoratedMeasurementInOther(view); } if (renderState.mLayoutDirection == RenderState.LAYOUT_START) { bottom = renderState.mOffset; top = renderState.mOffset - consumed; } else { top = renderState.mOffset; bottom = renderState.mOffset + consumed; } } else { if (renderState.mLayoutDirection == RenderState.LAYOUT_START) { bottom = getHeight() - getPaddingBottom() - itemWidth * columnCount; top = bottom - mOrientationHelper.getDecoratedMeasurementInOther(view); right = renderState.mOffset; left = renderState.mOffset - consumed; } else { top = columnCount * itemWidth + getPaddingTop(); bottom = top + mOrientationHelper.getDecoratedMeasurementInOther(view); left = renderState.mOffset; right = renderState.mOffset + consumed; } } // We calculate everything with View's bounding box (which includes decor and margins) // To calculate correct layout position, we subtract margins. layoutDecorated(view, left + params.leftMargin, top + params.topMargin , right - params.rightMargin, bottom - params.bottomMargin); if (DEBUG) { Log.d(TAG, "laid out child at position " + getPosition(view) + ", with l:" + (left + params.leftMargin) + ", t:" + (top + params.topMargin) + ", r:" + (right - params.rightMargin) + ", b:" + (bottom - params.bottomMargin)); } if (!params.isItemRemoved()) { columnCount++; if (columnCount == columns) { columnCount = 0; renderState.mOffset += consumed * renderState.mLayoutDirection; renderState.mAvailable -= consumed; // we keep a separate remaining space because mAvailable is important for recycling remainingSpace -= consumed; if (renderState.mScrollingOffset != RenderState.SCOLLING_OFFSET_NaN) { renderState.mScrollingOffset += consumed; if (renderState.mAvailable < 0) { renderState.mScrollingOffset += renderState.mAvailable; } recycleByRenderState(recycler, renderState); } } } if (stopOnFocusable && view.isFocusable()) { break; } if (state != null && state.getTargetScrollPosition() == getPosition(view)) { break; } } if (DEBUG) { validateChildOrder(); } return start - renderState.mAvailable; } }