Merge "Remove StaggeredGridView from support library and move to ex folder" into jb-dev
diff --git a/v4/java/android/support/v4/widget/StaggeredGridView.java b/v4/java/android/support/v4/widget/StaggeredGridView.java
deleted file mode 100644
index 4756215..0000000
--- a/v4/java/android/support/v4/widget/StaggeredGridView.java
+++ /dev/null
@@ -1,1619 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.support.v4.widget;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.graphics.Canvas;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.support.v4.util.SparseArrayCompat;
-import android.support.v4.view.MotionEventCompat;
-import android.support.v4.view.VelocityTrackerCompat;
-import android.support.v4.view.ViewCompat;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.widget.ListAdapter;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * ListView and GridView just not complex enough? Try StaggeredGridView!
- *
- * <p>StaggeredGridView presents a multi-column grid with consistent column sizes
- * but varying row sizes between the columns. Each successive item from a
- * {@link android.widget.ListAdapter ListAdapter} will be arranged from top to bottom,
- * left to right. The largest vertical gap is always filled first.</p>
- *
- * <p>Item views may span multiple columns as specified by their {@link LayoutParams}.
- * The attribute <code>android:layout_span</code> may be used when inflating
- * item views from xml.</p>
- */
-public class StaggeredGridView extends ViewGroup {
-    private static final String TAG = "StaggeredGridView";
-    private static final boolean DEBUG = false;
-
-    /*
-     * There are a few things you should know if you're going to make modifications
-     * to StaggeredGridView.
-     *
-     * Like ListView, SGV populates from an adapter and recycles views that fall out
-     * of the visible boundaries of the grid. A few invariants always hold:
-     *
-     * - mFirstPosition is the adapter position of the View returned by getChildAt(0).
-     * - Any child index can be translated to an adapter position by adding mFirstPosition.
-     * - Any adapter position can be translated to a child index by subtracting mFirstPosition.
-     * - Views for items in the range [mFirstPosition, mFirstPosition + getChildCount()) are
-     *   currently attached to the grid as children. All other adapter positions do not have
-     *   active views.
-     *
-     * This means a few things thanks to the staggered grid's nature. Some views may stay attached
-     * long after they have scrolled offscreen if removing and recycling them would result in
-     * breaking one of the invariants above.
-     *
-     * LayoutRecords are used to track data about a particular item's layout after the associated
-     * view has been removed. These let positioning and the choice of column for an item
-     * remain consistent even though the rules for filling content up vs. filling down vary.
-     *
-     * Whenever layout parameters for a known LayoutRecord change, other LayoutRecords before
-     * or after it may need to be invalidated. e.g. if the item's height or the number
-     * of columns it spans changes, all bets for other items in the same direction are off
-     * since the cached information no longer applies.
-     */
-
-    private ListAdapter mAdapter;
-
-    public static final int COLUMN_COUNT_AUTO = -1;
-
-    private int mColCountSetting = 2;
-    private int mColCount = 2;
-    private int mMinColWidth = 0;
-    private int mItemMargin;
-
-    private int[] mItemTops;
-    private int[] mItemBottoms;
-
-    private boolean mFastChildLayout;
-    private boolean mPopulating;
-    private boolean mForcePopulateOnLayout;
-    private boolean mInLayout;
-    private int mRestoreOffset;
-
-    private final RecycleBin mRecycler = new RecycleBin();
-
-    private final AdapterDataSetObserver mObserver = new AdapterDataSetObserver();
-
-    private boolean mDataChanged;
-    private int mOldItemCount;
-    private int mItemCount;
-    private boolean mHasStableIds;
-
-    private int mFirstPosition;
-
-    private int mTouchSlop;
-    private int mMaximumVelocity;
-    private int mFlingVelocity;
-    private float mLastTouchY;
-    private float mTouchRemainderY;
-    private int mActivePointerId;
-
-    private static final int TOUCH_MODE_IDLE = 0;
-    private static final int TOUCH_MODE_DRAGGING = 1;
-    private static final int TOUCH_MODE_FLINGING = 2;
-
-    private int mTouchMode;
-    private final VelocityTracker mVelocityTracker = VelocityTracker.obtain();
-    private final ScrollerCompat mScroller;
-
-    private final EdgeEffectCompat mTopEdge;
-    private final EdgeEffectCompat mBottomEdge;
-
-    private static final class LayoutRecord {
-        public int column;
-        public long id = -1;
-        public int height;
-        public int span;
-        private int[] mMargins;
-
-        private final void ensureMargins() {
-            if (mMargins == null) {
-                // Don't need to confirm length;
-                // all layoutrecords are purged when column count changes.
-                mMargins = new int[span * 2];
-            }
-        }
-
-        public final int getMarginAbove(int col) {
-            if (mMargins == null) {
-                return 0;
-            }
-            return mMargins[col * 2];
-        }
-
-        public final int getMarginBelow(int col) {
-            if (mMargins == null) {
-                return 0;
-            }
-            return mMargins[col * 2 + 1];
-        }
-
-        public final void setMarginAbove(int col, int margin) {
-            if (mMargins == null && margin == 0) {
-                return;
-            }
-            ensureMargins();
-            mMargins[col * 2] = margin;
-        }
-
-        public final void setMarginBelow(int col, int margin) {
-            if (mMargins == null && margin == 0) {
-                return;
-            }
-            ensureMargins();
-            mMargins[col * 2 + 1] = margin;
-        }
-
-        @Override
-        public String toString() {
-            String result = "LayoutRecord{c=" + column + ", id=" + id + " h=" + height +
-                    " s=" + span;
-            if (mMargins != null) {
-                result += " margins[above, below](";
-                for (int i = 0; i < mMargins.length; i += 2) {
-                    result += "[" + mMargins[i] + ", " + mMargins[i+1] + "]";
-                }
-                result += ")";
-            }
-            return result + "}";
-        }
-    }
-    private final SparseArrayCompat<LayoutRecord> mLayoutRecords =
-            new SparseArrayCompat<LayoutRecord>();
-
-    public StaggeredGridView(Context context) {
-        this(context, null);
-    }
-
-    public StaggeredGridView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public StaggeredGridView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        final ViewConfiguration vc = ViewConfiguration.get(context);
-        mTouchSlop = vc.getScaledTouchSlop();
-        mMaximumVelocity = vc.getScaledMaximumFlingVelocity();
-        mFlingVelocity = vc.getScaledMinimumFlingVelocity();
-        mScroller = ScrollerCompat.from(context);
-
-        mTopEdge = new EdgeEffectCompat(context);
-        mBottomEdge = new EdgeEffectCompat(context);
-        setWillNotDraw(false);
-        setClipToPadding(false);
-    }
-
-    /**
-     * Set a fixed number of columns for this grid. Space will be divided evenly
-     * among all columns, respecting the item margin between columns.
-     * The default is 2. (If it were 1, perhaps you should be using a
-     * {@link android.widget.ListView ListView}.)
-     *
-     * @param colCount Number of columns to display.
-     * @see #setMinColumnWidth(int)
-     */
-    public void setColumnCount(int colCount) {
-        if (colCount < 1 && colCount != COLUMN_COUNT_AUTO) {
-            throw new IllegalArgumentException("Column count must be at least 1 - received " +
-                    colCount);
-        }
-        final boolean needsPopulate = colCount != mColCount;
-        mColCount = mColCountSetting = colCount;
-        if (needsPopulate) {
-            populate();
-        }
-    }
-
-    public int getColumnCount() {
-        return mColCount;
-    }
-
-    /**
-     * Set a minimum column width for
-     * @param minColWidth
-     */
-    public void setMinColumnWidth(int minColWidth) {
-        mMinColWidth = minColWidth;
-        setColumnCount(COLUMN_COUNT_AUTO);
-    }
-
-    /**
-     * Set the margin between items in pixels. This margin is applied
-     * both vertically and horizontally.
-     *
-     * @param marginPixels Spacing between items in pixels
-     */
-    public void setItemMargin(int marginPixels) {
-        final boolean needsPopulate = marginPixels != mItemMargin;
-        mItemMargin = marginPixels;
-        if (needsPopulate) {
-            populate();
-        }
-    }
-
-    /**
-     * Return the first adapter position with a view currently attached as
-     * a child view of this grid.
-     *
-     * @return the adapter position represented by the view at getChildAt(0).
-     */
-    public int getFirstPosition() {
-        return mFirstPosition;
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        mVelocityTracker.addMovement(ev);
-        final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                mVelocityTracker.clear();
-                mScroller.abortAnimation();
-                mLastTouchY = ev.getY();
-                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
-                mTouchRemainderY = 0;
-                if (mTouchMode == TOUCH_MODE_FLINGING) {
-                    // Catch!
-                    mTouchMode = TOUCH_MODE_DRAGGING;
-                    return true;
-                }
-                break;
-
-            case MotionEvent.ACTION_MOVE: {
-                final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
-                if (index < 0) {
-                    Log.e(TAG, "onInterceptTouchEvent could not find pointer with id " +
-                            mActivePointerId + " - did StaggeredGridView receive an inconsistent " +
-                            "event stream?");
-                    return false;
-                }
-                final float y = MotionEventCompat.getY(ev, index);
-                final float dy = y - mLastTouchY + mTouchRemainderY;
-                final int deltaY = (int) dy;
-                mTouchRemainderY = dy - deltaY;
-
-                if (Math.abs(dy) > mTouchSlop) {
-                    mTouchMode = TOUCH_MODE_DRAGGING;
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        mVelocityTracker.addMovement(ev);
-        final int action = ev.getAction() & MotionEventCompat.ACTION_MASK;
-        switch (action) {
-            case MotionEvent.ACTION_DOWN:
-                mVelocityTracker.clear();
-                mScroller.abortAnimation();
-                mLastTouchY = ev.getY();
-                mActivePointerId = MotionEventCompat.getPointerId(ev, 0);
-                mTouchRemainderY = 0;
-                break;
-
-            case MotionEvent.ACTION_MOVE: {
-                final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
-                if (index < 0) {
-                    Log.e(TAG, "onInterceptTouchEvent could not find pointer with id " +
-                            mActivePointerId + " - did StaggeredGridView receive an inconsistent " +
-                            "event stream?");
-                    return false;
-                }
-                final float y = MotionEventCompat.getY(ev, index);
-                final float dy = y - mLastTouchY + mTouchRemainderY;
-                final int deltaY = (int) dy;
-                mTouchRemainderY = dy - deltaY;
-
-                if (Math.abs(dy) > mTouchSlop) {
-                    mTouchMode = TOUCH_MODE_DRAGGING;
-                }
-
-                if (mTouchMode == TOUCH_MODE_DRAGGING) {
-                    mLastTouchY = y;
-
-                    if (!trackMotionScroll(deltaY, true)) {
-                        // Break fling velocity if we impacted an edge.
-                        mVelocityTracker.clear();
-                    }
-                }
-            } break;
-
-            case MotionEvent.ACTION_CANCEL:
-                mTouchMode = TOUCH_MODE_IDLE;
-                break;
-
-            case MotionEvent.ACTION_UP: {
-                mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
-                final float velocity = VelocityTrackerCompat.getYVelocity(mVelocityTracker,
-                        mActivePointerId);
-                if (Math.abs(velocity) > mFlingVelocity) { // TODO
-                    mTouchMode = TOUCH_MODE_FLINGING;
-                    mScroller.fling(0, 0, 0, (int) velocity, 0, 0,
-                            Integer.MIN_VALUE, Integer.MAX_VALUE);
-                    mLastTouchY = 0;
-                    ViewCompat.postInvalidateOnAnimation(this);
-                } else {
-                    mTouchMode = TOUCH_MODE_IDLE;
-                }
-
-            } break;
-        }
-        return true;
-    }
-
-    /**
-     *
-     * @param deltaY Pixels that content should move by
-     * @return true if the movement completed, false if it was stopped prematurely.
-     */
-    private boolean trackMotionScroll(int deltaY, boolean allowOverScroll) {
-        final boolean contentFits = contentFits();
-        final int allowOverhang = Math.abs(deltaY);
-
-        final int overScrolledBy;
-        final int movedBy;
-        if (!contentFits) {
-            final int overhang;
-            final boolean up;
-            mPopulating = true;
-            if (deltaY > 0) {
-                overhang = fillUp(mFirstPosition - 1, allowOverhang);
-                up = true;
-            } else {
-                overhang = fillDown(mFirstPosition + getChildCount(), allowOverhang) + mItemMargin;
-                up = false;
-            }
-            movedBy = Math.min(overhang, allowOverhang);
-            offsetChildren(up ? movedBy : -movedBy);
-            recycleOffscreenViews();
-            mPopulating = false;
-            overScrolledBy = allowOverhang - overhang;
-        } else {
-            overScrolledBy = allowOverhang;
-            movedBy = 0;
-        }
-
-        if (allowOverScroll) {
-            final int overScrollMode = ViewCompat.getOverScrollMode(this);
-
-            if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS ||
-                    (overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS && !contentFits)) {
-
-                if (overScrolledBy > 0) {
-                    EdgeEffectCompat edge = deltaY > 0 ? mTopEdge : mBottomEdge;
-                    edge.onPull((float) Math.abs(deltaY) / getHeight());
-                    ViewCompat.postInvalidateOnAnimation(this);
-                }
-            }
-        }
-
-        return deltaY == 0 || movedBy != 0;
-    }
-
-    private final boolean contentFits() {
-        if (mFirstPosition != 0 || getChildCount() != mItemCount) {
-            return false;
-        }
-
-        int topmost = Integer.MAX_VALUE;
-        int bottommost = Integer.MIN_VALUE;
-        for (int i = 0; i < mColCount; i++) {
-            if (mItemTops[i] < topmost) {
-                topmost = mItemTops[i];
-            }
-            if (mItemBottoms[i] > bottommost) {
-                bottommost = mItemBottoms[i];
-            }
-        }
-
-        return topmost >= getPaddingTop() && bottommost <= getHeight() - getPaddingBottom();
-    }
-
-    private void recycleAllViews() {
-        for (int i = 0; i < getChildCount(); i++) {
-            mRecycler.addScrap(getChildAt(i));
-        }
-
-        if (mInLayout) {
-            removeAllViewsInLayout();
-        } else {
-            removeAllViews();
-        }
-    }
-
-    /**
-     * Important: this method will leave offscreen views attached if they
-     * are required to maintain the invariant that child view with index i
-     * is always the view corresponding to position mFirstPosition + i.
-     */
-    private void recycleOffscreenViews() {
-        final int height = getHeight();
-        final int clearAbove = -mItemMargin;
-        final int clearBelow = height + mItemMargin;
-        for (int i = getChildCount() - 1; i >= 0; i--) {
-            final View child = getChildAt(i);
-            if (child.getTop() <= clearBelow)  {
-                // There may be other offscreen views, but we need to maintain
-                // the invariant documented above.
-                break;
-            }
-
-            if (mInLayout) {
-                removeViewsInLayout(i, 1);
-            } else {
-                removeViewAt(i);
-            }
-
-            mRecycler.addScrap(child);
-        }
-
-        while (getChildCount() > 0) {
-            final View child = getChildAt(0);
-            if (child.getBottom() >= clearAbove) {
-                // There may be other offscreen views, but we need to maintain
-                // the invariant documented above.
-                break;
-            }
-
-            if (mInLayout) {
-                removeViewsInLayout(0, 1);
-            } else {
-                removeViewAt(0);
-            }
-
-            mRecycler.addScrap(child);
-            mFirstPosition++;
-        }
-
-        final int childCount = getChildCount();
-        if (childCount > 0) {
-            // Repair the top and bottom column boundaries from the views we still have
-            Arrays.fill(mItemTops, Integer.MAX_VALUE);
-            Arrays.fill(mItemBottoms, Integer.MIN_VALUE);
-
-            for (int i = 0; i < childCount; i++){
-                final View child = getChildAt(i);
-                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                final int top = child.getTop() - mItemMargin;
-                final int bottom = child.getBottom();
-                final LayoutRecord rec = mLayoutRecords.get(mFirstPosition + i);
-
-                final int colEnd = lp.column + Math.min(mColCount, lp.span);
-                for (int col = lp.column; col < colEnd; col++) {
-                    final int colTop = top - rec.getMarginAbove(col - lp.column);
-                    final int colBottom = bottom + rec.getMarginBelow(col - lp.column);
-                    if (colTop < mItemTops[col]) {
-                        mItemTops[col] = colTop;
-                    }
-                    if (colBottom > mItemBottoms[col]) {
-                        mItemBottoms[col] = colBottom;
-                    }
-                }
-            }
-
-            for (int col = 0; col < mColCount; col++) {
-                if (mItemTops[col] == Integer.MAX_VALUE) {
-                    // If one was untouched, both were.
-                    mItemTops[col] = 0;
-                    mItemBottoms[col] = 0;
-                }
-            }
-        }
-    }
-
-    public void computeScroll() {
-        if (mScroller.computeScrollOffset()) {
-            final int y = mScroller.getCurrY();
-            final int dy = (int) (y - mLastTouchY);
-            mLastTouchY = y;
-            final boolean stopped = !trackMotionScroll(dy, false);
-
-            if (!stopped && !mScroller.isFinished()) {
-                ViewCompat.postInvalidateOnAnimation(this);
-            } else {
-                if (stopped) {
-                    final int overScrollMode = ViewCompat.getOverScrollMode(this);
-                    if (overScrollMode != ViewCompat.OVER_SCROLL_NEVER) {
-                        final EdgeEffectCompat edge;
-                        if (dy > 0) {
-                            edge = mTopEdge;
-                        } else {
-                            edge = mBottomEdge;
-                        }
-                        edge.onAbsorb(Math.abs((int) mScroller.getCurrVelocity()));
-                        ViewCompat.postInvalidateOnAnimation(this);
-                    }
-                    mScroller.abortAnimation();
-                }
-                mTouchMode = TOUCH_MODE_IDLE;
-            }
-        }
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        super.draw(canvas);
-
-        if (mTopEdge != null) {
-            boolean needsInvalidate = false;
-            if (!mTopEdge.isFinished()) {
-                mTopEdge.draw(canvas);
-                needsInvalidate = true;
-            }
-            if (!mBottomEdge.isFinished()) {
-                final int restoreCount = canvas.save();
-                final int width = getWidth();
-                canvas.translate(-width, getHeight());
-                canvas.rotate(180, width, 0);
-                mBottomEdge.draw(canvas);
-                canvas.restoreToCount(restoreCount);
-                needsInvalidate = true;
-            }
-
-            if (needsInvalidate) {
-                ViewCompat.postInvalidateOnAnimation(this);
-            }
-        }
-    }
-
-    public void beginFastChildLayout() {
-        mFastChildLayout = true;
-    }
-
-    public void endFastChildLayout() {
-        mFastChildLayout = false;
-        populate();
-    }
-
-    @Override
-    public void requestLayout() {
-        if (!mPopulating && !mFastChildLayout) {
-            super.requestLayout();
-        }
-    }
-
-    @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) {
-            Log.e(TAG, "onMeasure: must have an exact width or match_parent! " +
-                    "Using fallback spec of EXACTLY " + widthSize);
-            widthMode = MeasureSpec.EXACTLY;
-        }
-        if (heightMode != MeasureSpec.EXACTLY) {
-            Log.e(TAG, "onMeasure: must have an exact height or match_parent! " +
-                    "Using fallback spec of EXACTLY " + heightSize);
-            heightMode = MeasureSpec.EXACTLY;
-        }
-
-        setMeasuredDimension(widthSize, heightSize);
-
-        if (mColCountSetting == COLUMN_COUNT_AUTO) {
-            final int colCount = widthSize / mMinColWidth;
-            if (colCount != mColCount) {
-                mColCount = colCount;
-                mForcePopulateOnLayout = true;
-            }
-        }
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        mInLayout = true;
-        populate();
-        mInLayout = false;
-        mForcePopulateOnLayout = false;
-
-        final int width = r - l;
-        final int height = b - t;
-        mTopEdge.setSize(width, height);
-        mBottomEdge.setSize(width, height);
-    }
-
-    private void populate() {
-        if (getWidth() == 0 || getHeight() == 0) {
-            return;
-        }
-
-        if (mColCount == COLUMN_COUNT_AUTO) {
-            final int colCount = getWidth() / mMinColWidth;
-            if (colCount != mColCount) {
-                mColCount = colCount;
-            }
-        }
-
-        final int colCount = mColCount;
-        if (mItemTops == null || mItemTops.length != colCount) {
-            mItemTops = new int[colCount];
-            mItemBottoms = new int[colCount];
-            final int top = getPaddingTop();
-            final int offset = top + Math.min(mRestoreOffset, 0);
-            Arrays.fill(mItemTops, offset);
-            Arrays.fill(mItemBottoms, offset);
-            mLayoutRecords.clear();
-            if (mInLayout) {
-                removeAllViewsInLayout();
-            } else {
-                removeAllViews();
-            }
-            mRestoreOffset = 0;
-        }
-
-        mPopulating = true;
-        layoutChildren(mDataChanged);
-        fillDown(mFirstPosition + getChildCount(), 0);
-        fillUp(mFirstPosition - 1, 0);
-        mPopulating = false;
-        mDataChanged = false;
-    }
-
-    private void dumpItemPositions() {
-        final int childCount = getChildCount();
-        Log.d(TAG, "dumpItemPositions:");
-        Log.d(TAG, " => Tops:");
-        for (int i = 0; i < mColCount; i++) {
-            Log.d(TAG, "  => " + mItemTops[i]);
-            boolean found = false;
-            for (int j = 0; j < childCount; j++) {
-                final View child = getChildAt(j);
-                if (mItemTops[i] == child.getTop() - mItemMargin) {
-                    found = true;
-                }
-            }
-            if (!found) {
-                Log.d(TAG, "!!! No top item found for column " + i + " value " + mItemTops[i]);
-            }
-        }
-        Log.d(TAG, " => Bottoms:");
-        for (int i = 0; i < mColCount; i++) {
-            Log.d(TAG, "  => " + mItemBottoms[i]);
-            boolean found = false;
-            for (int j = 0; j < childCount; j++) {
-                final View child = getChildAt(j);
-                if (mItemBottoms[i] == child.getBottom()) {
-                    found = true;
-                }
-            }
-            if (!found) {
-                Log.d(TAG, "!!! No bottom item found for column " + i + " value " + mItemBottoms[i]);
-            }
-        }
-    }
-
-    final void offsetChildren(int offset) {
-        final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            final View child = getChildAt(i);
-            child.layout(child.getLeft(), child.getTop() + offset,
-                    child.getRight(), child.getBottom() + offset);
-        }
-
-        final int colCount = mColCount;
-        for (int i = 0; i < colCount; i++) {
-            mItemTops[i] += offset;
-            mItemBottoms[i] += offset;
-        }
-    }
-
-    /**
-     * Measure and layout all currently visible children.
-     *
-     * @param queryAdapter true to requery the adapter for view data
-     */
-    final void layoutChildren(boolean queryAdapter) {
-        final int paddingLeft = getPaddingLeft();
-        final int paddingRight = getPaddingRight();
-        final int itemMargin = mItemMargin;
-        final int colWidth =
-                (getWidth() - paddingLeft - paddingRight - itemMargin * (mColCount - 1)) / mColCount;
-        int rebuildLayoutRecordsBefore = -1;
-        int rebuildLayoutRecordsAfter = -1;
-
-        Arrays.fill(mItemBottoms, Integer.MIN_VALUE);
-
-        final int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            LayoutParams lp = (LayoutParams) child.getLayoutParams();
-            final int col = lp.column;
-            final int position = mFirstPosition + i;
-            final boolean needsLayout = queryAdapter || child.isLayoutRequested();
-
-            if (queryAdapter) {
-                View newView = obtainView(position, child);
-                if (newView != child) {
-                    removeViewAt(i);
-                    addView(newView, i);
-                    child = newView;
-                }
-                lp = (LayoutParams) child.getLayoutParams(); // Might have changed
-            }
-
-            final int span = Math.min(mColCount, lp.span);
-            final int widthSize = colWidth * span + itemMargin * (span - 1);
-
-            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);
-            }
-
-            int childTop = mItemBottoms[col] > Integer.MIN_VALUE ?
-                    mItemBottoms[col] + mItemMargin : child.getTop();
-            if (span > 1) {
-                int lowest = childTop;
-                for (int j = col + 1; j < col + span; j++) {
-                    final int bottom = mItemBottoms[j] + mItemMargin;
-                    if (bottom > lowest) {
-                        lowest = bottom;
-                    }
-                }
-                childTop = lowest;
-            }
-            final int childHeight = child.getMeasuredHeight();
-            final int childBottom = childTop + childHeight;
-            final int childLeft = paddingLeft + col * (colWidth + itemMargin);
-            final int childRight = childLeft + child.getMeasuredWidth();
-            child.layout(childLeft, childTop, childRight, childBottom);
-
-            for (int j = col; j < col + span; j++) {
-                mItemBottoms[j] = childBottom;
-            }
-
-            final LayoutRecord rec = mLayoutRecords.get(position);
-            if (rec != null && rec.height != childHeight) {
-                // Invalidate our layout records for everything before this.
-                rec.height = childHeight;
-                rebuildLayoutRecordsBefore = position;
-            }
-
-            if (rec != null && rec.span != span) {
-                // Invalidate our layout records for everything after this.
-                rec.span = span;
-                rebuildLayoutRecordsAfter = position;
-            }
-        }
-
-        // Update mItemBottoms for any empty columns
-        for (int i = 0; i < mColCount; i++) {
-            if (mItemBottoms[i] == Integer.MIN_VALUE) {
-                mItemBottoms[i] = mItemTops[i];
-            }
-        }
-
-        if (rebuildLayoutRecordsBefore >= 0 || rebuildLayoutRecordsAfter >= 0) {
-            if (rebuildLayoutRecordsBefore >= 0) {
-                invalidateLayoutRecordsBeforePosition(rebuildLayoutRecordsBefore);
-            }
-            if (rebuildLayoutRecordsAfter >= 0) {
-                invalidateLayoutRecordsAfterPosition(rebuildLayoutRecordsAfter);
-            }
-            for (int i = 0; i < childCount; i++) {
-                final int position = mFirstPosition + i;
-                final View child = getChildAt(i);
-                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-                LayoutRecord rec = mLayoutRecords.get(position);
-                if (rec == null) {
-                    rec = new LayoutRecord();
-                    mLayoutRecords.put(position, rec);
-                }
-                rec.column = lp.column;
-                rec.height = child.getHeight();
-                rec.id = lp.id;
-                rec.span = Math.min(mColCount, lp.span);
-            }
-        }
-    }
-
-    final void invalidateLayoutRecordsBeforePosition(int position) {
-        int endAt = 0;
-        while (endAt < mLayoutRecords.size() && mLayoutRecords.keyAt(endAt) < position) {
-            endAt++;
-        }
-        mLayoutRecords.removeAtRange(0, endAt);
-    }
-
-    final void invalidateLayoutRecordsAfterPosition(int position) {
-        int beginAt = mLayoutRecords.size() - 1;
-        while (beginAt >= 0 && mLayoutRecords.keyAt(beginAt) > position) {
-            beginAt--;
-        }
-        beginAt++;
-        mLayoutRecords.removeAtRange(beginAt + 1, mLayoutRecords.size() - beginAt);
-    }
-
-    /**
-     * Should be called with mPopulating set to true
-     *
-     * @param fromPosition Position to start filling from
-     * @param overhang the number of extra pixels to fill beyond the current top edge
-     * @return the max overhang beyond the beginning of the view of any added items at the top
-     */
-    final int fillUp(int fromPosition, int overhang) {
-        final int paddingLeft = getPaddingLeft();
-        final int paddingRight = getPaddingRight();
-        final int itemMargin = mItemMargin;
-        final int colWidth =
-                (getWidth() - paddingLeft - paddingRight - itemMargin * (mColCount - 1)) / mColCount;
-        final int gridTop = getPaddingTop();
-        final int fillTo = gridTop - overhang;
-        int nextCol = getNextColumnUp();
-        int position = fromPosition;
-
-        while (nextCol >= 0 && mItemTops[nextCol] > fillTo && position >= 0) {
-            final View child = obtainView(position, null);
-            LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
-            if (child.getParent() != this) {
-                if (mInLayout) {
-                    addViewInLayout(child, 0, lp);
-                } else {
-                    addView(child, 0);
-                }
-            }
-
-            final int span = Math.min(mColCount, lp.span);
-            final int widthSize = colWidth * span + itemMargin * (span - 1);
-            final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
-
-            LayoutRecord rec;
-            if (span > 1) {
-                rec = getNextRecordUp(position, span);
-                nextCol = rec.column;
-            } else {
-                rec = mLayoutRecords.get(position);
-            }
-
-            boolean invalidateBefore = false;
-            if (rec == null) {
-                rec = new LayoutRecord();
-                mLayoutRecords.put(position, rec);
-                rec.column = nextCol;
-                rec.span = span;
-            } else if (span != rec.span) {
-                rec.span = span;
-                rec.column = nextCol;
-                invalidateBefore = true;
-            } else {
-                nextCol = rec.column;
-            }
-
-            if (mHasStableIds) {
-                final long id = mAdapter.getItemId(position);
-                rec.id = id;
-                lp.id = id;
-            }
-
-            lp.column = nextCol;
-
-            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);
-
-            final int childHeight = child.getMeasuredHeight();
-            if (invalidateBefore || (childHeight != rec.height && rec.height > 0)) {
-                invalidateLayoutRecordsBeforePosition(position);
-            }
-            rec.height = childHeight;
-
-            final int startFrom;
-            if (span > 1) {
-                int highest = mItemTops[nextCol];
-                for (int i = nextCol + 1; i < nextCol + span; i++) {
-                    final int top = mItemTops[i];
-                    if (top < highest) {
-                        highest = top;
-                    }
-                }
-                startFrom = highest;
-            } else {
-                startFrom = mItemTops[nextCol];
-            }
-            final int childBottom = startFrom;
-            final int childTop = childBottom - childHeight;
-            final int childLeft = paddingLeft + nextCol * (colWidth + itemMargin);
-            final int childRight = childLeft + child.getMeasuredWidth();
-            child.layout(childLeft, childTop, childRight, childBottom);
-
-            for (int i = nextCol; i < nextCol + span; i++) {
-                mItemTops[i] = childTop - rec.getMarginAbove(i - nextCol) - itemMargin;
-            }
-
-            nextCol = getNextColumnUp();
-            mFirstPosition = position--;
-        }
-
-        int highestView = getHeight();
-        for (int i = 0; i < mColCount; i++) {
-            if (mItemTops[i] < highestView) {
-                highestView = mItemTops[i];
-            }
-        }
-        return gridTop - highestView;
-    }
-
-    /**
-     * Should be called with mPopulating set to true
-     *
-     * @param fromPosition Position to start filling from
-     * @param overhang the number of extra pixels to fill beyond the current bottom edge
-     * @return the max overhang beyond the end of the view of any added items at the bottom
-     */
-    final int fillDown(int fromPosition, int overhang) {
-        final int paddingLeft = getPaddingLeft();
-        final int paddingRight = getPaddingRight();
-        final int itemMargin = mItemMargin;
-        final int colWidth =
-                (getWidth() - paddingLeft - paddingRight - itemMargin * (mColCount - 1)) / mColCount;
-        final int gridBottom = getHeight() - getPaddingBottom();
-        final int fillTo = gridBottom + overhang;
-        int nextCol = getNextColumnDown();
-        int position = fromPosition;
-
-        while (nextCol >= 0 && mItemBottoms[nextCol] < fillTo && position < mItemCount) {
-            final View child = obtainView(position, null);
-            LayoutParams lp = (LayoutParams) child.getLayoutParams();
-
-            if (child.getParent() != this) {
-                if (mInLayout) {
-                    addViewInLayout(child, -1, lp);
-                } else {
-                    addView(child);
-                }
-            }
-
-            final int span = Math.min(mColCount, lp.span);
-            final int widthSize = colWidth * span + itemMargin * (span - 1);
-            final int widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
-
-            LayoutRecord rec;
-            if (span > 1) {
-                rec = getNextRecordDown(position, span);
-                nextCol = rec.column;
-            } else {
-                rec = mLayoutRecords.get(position);
-            }
-
-            boolean invalidateAfter = false;
-            if (rec == null) {
-                rec = new LayoutRecord();
-                mLayoutRecords.put(position, rec);
-                rec.column = nextCol;
-                rec.span = span;
-            } else if (span != rec.span) {
-                rec.span = span;
-                rec.column = nextCol;
-                invalidateAfter = true;
-            } else {
-                nextCol = rec.column;
-            }
-
-            if (mHasStableIds) {
-                final long id = mAdapter.getItemId(position);
-                rec.id = id;
-                lp.id = id;
-            }
-
-            lp.column = nextCol;
-
-            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);
-
-            final int childHeight = child.getMeasuredHeight();
-            if (invalidateAfter || (childHeight != rec.height && rec.height > 0)) {
-                invalidateLayoutRecordsAfterPosition(position);
-            }
-            rec.height = childHeight;
-
-            final int startFrom;
-            if (span > 1) {
-                int lowest = mItemBottoms[nextCol];
-                for (int i = nextCol + 1; i < nextCol + span; i++) {
-                    final int bottom = mItemBottoms[i];
-                    if (bottom > lowest) {
-                        lowest = bottom;
-                    }
-                }
-                startFrom = lowest;
-            } else {
-                startFrom = mItemBottoms[nextCol];
-            }
-            final int childTop = startFrom + itemMargin;
-            final int childBottom = childTop + childHeight;
-            final int childLeft = paddingLeft + nextCol * (colWidth + itemMargin);
-            final int childRight = childLeft + child.getMeasuredWidth();
-            child.layout(childLeft, childTop, childRight, childBottom);
-
-            for (int i = nextCol; i < nextCol + span; i++) {
-                mItemBottoms[i] = childBottom + rec.getMarginBelow(i - nextCol);
-            }
-
-            nextCol = getNextColumnDown();
-            position++;
-        }
-
-        int lowestView = 0;
-        for (int i = 0; i < mColCount; i++) {
-            if (mItemBottoms[i] > lowestView) {
-                lowestView = mItemBottoms[i];
-            }
-        }
-        return lowestView - gridBottom;
-    }
-
-    /**
-     * @return column that the next view filling upwards should occupy. This is the bottom-most
-     *         position available for a single-column item.
-     */
-    final int getNextColumnUp() {
-        int result = -1;
-        int bottomMost = Integer.MIN_VALUE;
-
-        final int colCount = mColCount;
-        for (int i = colCount - 1; i >= 0; i--) {
-            final int top = mItemTops[i];
-            if (top > bottomMost) {
-                bottomMost = top;
-                result = i;
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Return a LayoutRecord for the given position
-     * @param position
-     * @param span
-     * @return
-     */
-    final LayoutRecord getNextRecordUp(int position, int span) {
-        LayoutRecord rec = mLayoutRecords.get(position);
-        if (rec == null) {
-            rec = new LayoutRecord();
-            rec.span = span;
-            mLayoutRecords.put(position, rec);
-        } else if (rec.span != span) {
-            throw new IllegalStateException("Invalid LayoutRecord! Record had span=" + rec.span +
-                    " but caller requested span=" + span + " for position=" + position);
-        }
-        int targetCol = -1;
-        int bottomMost = Integer.MIN_VALUE;
-
-        final int colCount = mColCount;
-        for (int i = colCount - span; i >= 0; i--) {
-            int top = Integer.MAX_VALUE;
-            for (int j = i; j < i + span; j++) {
-                final int singleTop = mItemTops[j];
-                if (singleTop < top) {
-                    top = singleTop;
-                }
-            }
-            if (top > bottomMost) {
-                bottomMost = top;
-                targetCol = i;
-            }
-        }
-
-        rec.column = targetCol;
-
-        for (int i = 0; i < span; i++) {
-            rec.setMarginBelow(i, mItemTops[i + targetCol] - bottomMost);
-        }
-
-        return rec;
-    }
-
-    /**
-     * @return column that the next view filling downwards should occupy. This is the top-most
-     *         position available.
-     */
-    final int getNextColumnDown() {
-        int result = -1;
-        int topMost = Integer.MAX_VALUE;
-
-        final int colCount = mColCount;
-        for (int i = 0; i < colCount; i++) {
-            final int bottom = mItemBottoms[i];
-            if (bottom < topMost) {
-                topMost = bottom;
-                result = i;
-            }
-        }
-        return result;
-    }
-
-    final LayoutRecord getNextRecordDown(int position, int span) {
-        LayoutRecord rec = mLayoutRecords.get(position);
-        if (rec == null) {
-            rec = new LayoutRecord();
-            rec.span = span;
-            mLayoutRecords.put(position, rec);
-        } else if (rec.span != span) {
-            throw new IllegalStateException("Invalid LayoutRecord! Record had span=" + rec.span +
-                    " but caller requested span=" + span + " for position=" + position);
-        }
-        int targetCol = -1;
-        int topMost = Integer.MAX_VALUE;
-
-        final int colCount = mColCount;
-        for (int i = 0; i <= colCount - span; i++) {
-            int bottom = Integer.MIN_VALUE;
-            for (int j = i; j < i + span; j++) {
-                final int singleBottom = mItemBottoms[j];
-                if (singleBottom > bottom) {
-                    bottom = singleBottom;
-                }
-            }
-            if (bottom < topMost) {
-                topMost = bottom;
-                targetCol = i;
-            }
-        }
-
-        rec.column = targetCol;
-
-        for (int i = 0; i < span; i++) {
-            rec.setMarginAbove(i, topMost - mItemBottoms[i + targetCol]);
-        }
-
-        return rec;
-    }
-
-    /**
-     * Obtain a populated view from the adapter. If optScrap is non-null and is not
-     * reused it will be placed in the recycle bin.
-     *
-     * @param position position to get view for
-     * @param optScrap Optional scrap view; will be reused if possible
-     * @return A new view, a recycled view from mRecycler, or optScrap
-     */
-    final View obtainView(int position, View optScrap) {
-        View view = mRecycler.getTransientStateView(position);
-        if (view != null) {
-            return view;
-        }
-
-        // Reuse optScrap if it's of the right type (and not null)
-        final int optType = optScrap != null ?
-                ((LayoutParams) optScrap.getLayoutParams()).viewType : -1;
-        final int positionViewType = mAdapter.getItemViewType(position);
-        final View scrap = optType == positionViewType ?
-                optScrap : mRecycler.getScrapView(positionViewType);
-
-        view = mAdapter.getView(position, scrap, this);
-
-        if (view != scrap && scrap != null) {
-            // The adapter didn't use it; put it back.
-            mRecycler.addScrap(scrap);
-        }
-
-        ViewGroup.LayoutParams lp = view.getLayoutParams();
-
-        if (view.getParent() != this) {
-            if (lp == null) {
-                lp = generateDefaultLayoutParams();
-            } else if (!checkLayoutParams(lp)) {
-                lp = generateLayoutParams(lp);
-            }
-        }
-
-        final LayoutParams sglp = (LayoutParams) lp;
-        sglp.position = position;
-        sglp.viewType = positionViewType;
-
-        return view;
-    }
-
-    public ListAdapter getAdapter() {
-        return mAdapter;
-    }
-
-    public void setAdapter(ListAdapter adapter) {
-        if (mAdapter != null) {
-            mAdapter.unregisterDataSetObserver(mObserver);
-        }
-        // TODO: If the new adapter says that there are stable IDs, remove certain layout records
-        // and onscreen views if they have changed instead of removing all of the state here.
-        clearAllState();
-        mAdapter = adapter;
-        mDataChanged = true;
-        mOldItemCount = mItemCount = adapter != null ? adapter.getCount() : 0;
-        if (adapter != null) {
-            adapter.registerDataSetObserver(mObserver);
-            mRecycler.setViewTypeCount(adapter.getViewTypeCount());
-            mHasStableIds = adapter.hasStableIds();
-        } else {
-            mHasStableIds = false;
-        }
-        populate();
-    }
-
-    /**
-     * Clear all state because the grid will be used for a completely different set of data.
-     */
-    private void clearAllState() {
-        // Clear all layout records and views
-        mLayoutRecords.clear();
-        removeAllViews();
-
-        // Reset to the top of the grid
-        resetStateForGridTop();
-
-        // Clear recycler because there could be different view types now
-        mRecycler.clear();
-    }
-
-    /**
-     * Reset all internal state to be at the top of the grid.
-     */
-    private void resetStateForGridTop() {
-        // Reset mItemTops and mItemBottoms
-        final int colCount = mColCount;
-        if (mItemTops == null || mItemTops.length != colCount) {
-            mItemTops = new int[colCount];
-            mItemBottoms = new int[colCount];
-        }
-        final int top = getPaddingTop();
-        Arrays.fill(mItemTops, top);
-        Arrays.fill(mItemBottoms, top);
-
-        // Reset the first visible position in the grid to be item 0
-        mFirstPosition = 0;
-        mRestoreOffset = 0;
-    }
-
-    /**
-     * Scroll the list so the first visible position in the grid is the first item in the adapter.
-     */
-    public void setSelectionToTop() {
-        // Clear out the views (but don't clear out the layout records or recycler because the data
-        // has not changed)
-        removeAllViews();
-
-        // Reset to top of grid
-        resetStateForGridTop();
-
-        // Start populating again
-        populate();
-    }
-
-    @Override
-    protected LayoutParams generateDefaultLayoutParams() {
-        return new LayoutParams(LayoutParams.WRAP_CONTENT);
-    }
-
-    @Override
-    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
-        return new LayoutParams(lp);
-    }
-
-    @Override
-    protected boolean checkLayoutParams(ViewGroup.LayoutParams lp) {
-        return lp instanceof LayoutParams;
-    }
-
-    @Override
-    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
-        return new LayoutParams(getContext(), attrs);
-    }
-
-    @Override
-    public Parcelable onSaveInstanceState() {
-        final Parcelable superState = super.onSaveInstanceState();
-        final SavedState ss = new SavedState(superState);
-        final int position = mFirstPosition;
-        ss.position = position;
-        if (position >= 0 && mAdapter != null && position < mAdapter.getCount()) {
-            ss.firstId = mAdapter.getItemId(position);
-        }
-        if (getChildCount() > 0) {
-            ss.topOffset = getChildAt(0).getTop() - mItemMargin - getPaddingTop();
-        }
-        return ss;
-    }
-
-    @Override
-    public void onRestoreInstanceState(Parcelable state) {
-        SavedState ss = (SavedState) state;
-        super.onRestoreInstanceState(ss.getSuperState());
-        mDataChanged = true;
-        mFirstPosition = ss.position;
-        mRestoreOffset = ss.topOffset;
-        requestLayout();
-    }
-
-    public static class LayoutParams extends ViewGroup.LayoutParams {
-        private static final int[] LAYOUT_ATTRS = new int[] {
-            android.R.attr.layout_span
-        };
-
-        private static final int SPAN_INDEX = 0;
-
-        /**
-         * The number of columns this item should span
-         */
-        public int span = 1;
-
-        /**
-         * Item position this view represents
-         */
-        int position;
-
-        /**
-         * Type of this view as reported by the adapter
-         */
-        int viewType;
-
-        /**
-         * The column this view is occupying
-         */
-        int column;
-
-        /**
-         * The stable ID of the item this view displays
-         */
-        long id = -1;
-
-        public LayoutParams(int height) {
-            super(FILL_PARENT, height);
-
-            if (this.height == FILL_PARENT) {
-                Log.w(TAG, "Constructing LayoutParams with height FILL_PARENT - " +
-                        "impossible! Falling back to WRAP_CONTENT");
-                this.height = WRAP_CONTENT;
-            }
-        }
-
-        public LayoutParams(Context c, AttributeSet attrs) {
-            super(c, attrs);
-
-            if (this.width != FILL_PARENT) {
-                Log.w(TAG, "Inflation setting LayoutParams width to " + this.width +
-                        " - must be MATCH_PARENT");
-                this.width = FILL_PARENT;
-            }
-            if (this.height == FILL_PARENT) {
-                Log.w(TAG, "Inflation setting LayoutParams height to MATCH_PARENT - " +
-                        "impossible! Falling back to WRAP_CONTENT");
-                this.height = WRAP_CONTENT;
-            }
-
-            TypedArray a = c.obtainStyledAttributes(attrs, LAYOUT_ATTRS);
-            span = a.getInteger(SPAN_INDEX, 1);
-            a.recycle();
-        }
-
-        public LayoutParams(ViewGroup.LayoutParams other) {
-            super(other);
-
-            if (this.width != FILL_PARENT) {
-                Log.w(TAG, "Constructing LayoutParams with width " + this.width +
-                        " - must be MATCH_PARENT");
-                this.width = FILL_PARENT;
-            }
-            if (this.height == FILL_PARENT) {
-                Log.w(TAG, "Constructing LayoutParams with height MATCH_PARENT - " +
-                        "impossible! Falling back to WRAP_CONTENT");
-                this.height = WRAP_CONTENT;
-            }
-        }
-    }
-
-    private class RecycleBin {
-        private ArrayList<View>[] mScrapViews;
-        private int mViewTypeCount;
-        private int mMaxScrap;
-
-        private SparseArray<View> mTransientStateViews;
-
-        public void setViewTypeCount(int viewTypeCount) {
-            if (viewTypeCount < 1) {
-                throw new IllegalArgumentException("Must have at least one view type (" +
-                        viewTypeCount + " types reported)");
-            }
-            if (viewTypeCount == mViewTypeCount) {
-                return;
-            }
-
-            ArrayList<View>[] scrapViews = new ArrayList[viewTypeCount];
-            for (int i = 0; i < viewTypeCount; i++) {
-                scrapViews[i] = new ArrayList<View>();
-            }
-            mViewTypeCount = viewTypeCount;
-            mScrapViews = scrapViews;
-        }
-
-        public void clear() {
-            final int typeCount = mViewTypeCount;
-            for (int i = 0; i < typeCount; i++) {
-                mScrapViews[i].clear();
-            }
-            if (mTransientStateViews != null) {
-                mTransientStateViews.clear();
-            }
-        }
-
-        public void clearTransientViews() {
-            if (mTransientStateViews != null) {
-                mTransientStateViews.clear();
-            }
-        }
-
-        public void addScrap(View v) {
-            final LayoutParams lp = (LayoutParams) v.getLayoutParams();
-            if (ViewCompat.hasTransientState(v)) {
-                if (mTransientStateViews == null) {
-                    mTransientStateViews = new SparseArray<View>();
-                }
-                mTransientStateViews.put(lp.position, v);
-                return;
-            }
-
-            final int childCount = getChildCount();
-            if (childCount > mMaxScrap) {
-                mMaxScrap = childCount;
-            }
-
-            ArrayList<View> scrap = mScrapViews[lp.viewType];
-            if (scrap.size() < mMaxScrap) {
-                scrap.add(v);
-            }
-        }
-
-        public View getTransientStateView(int position) {
-            if (mTransientStateViews == null) {
-                return null;
-            }
-
-            final View result = mTransientStateViews.get(position);
-            if (result != null) {
-                mTransientStateViews.remove(position);
-            }
-            return result;
-        }
-
-        public View getScrapView(int type) {
-            ArrayList<View> scrap = mScrapViews[type];
-            if (scrap.isEmpty()) {
-                return null;
-            }
-
-            final int index = scrap.size() - 1;
-            final View result = scrap.get(index);
-            scrap.remove(index);
-            return result;
-        }
-    }
-
-    private class AdapterDataSetObserver extends DataSetObserver {
-        @Override
-        public void onChanged() {
-            mDataChanged = true;
-            mOldItemCount = mItemCount;
-            mItemCount = mAdapter.getCount();
-
-            // TODO: Consider matching these back up if we have stable IDs.
-            mRecycler.clearTransientViews();
-
-            if (!mHasStableIds) {
-                // Clear all layout records and recycle the views
-                mLayoutRecords.clear();
-                recycleAllViews();
-
-                // Reset item bottoms to be equal to item tops
-                final int colCount = mColCount;
-                for (int i = 0; i < colCount; i++) {
-                    mItemBottoms[i] = mItemTops[i];
-                }
-            }
-
-            // TODO: consider repopulating in a deferred runnable instead
-            // (so that successive changes may still be batched)
-            requestLayout();
-        }
-
-        @Override
-        public void onInvalidated() {
-        }
-    }
-
-    static class SavedState extends BaseSavedState {
-        long firstId = -1;
-        int position;
-        int topOffset;
-
-        SavedState(Parcelable superState) {
-            super(superState);
-        }
-
-        private SavedState(Parcel in) {
-            super(in);
-            firstId = in.readLong();
-            position = in.readInt();
-            topOffset = in.readInt();
-        }
-
-        @Override
-        public void writeToParcel(Parcel out, int flags) {
-            super.writeToParcel(out, flags);
-            out.writeLong(firstId);
-            out.writeInt(position);
-            out.writeInt(topOffset);
-        }
-
-        @Override
-        public String toString() {
-            return "StaggereGridView.SavedState{"
-			+ Integer.toHexString(System.identityHashCode(this))
-			+ " firstId=" + firstId
-			+ " position=" + position + "}";
-        }
-
-        public static final Parcelable.Creator<SavedState> CREATOR
-                = new Parcelable.Creator<SavedState>() {
-            public SavedState createFromParcel(Parcel in) {
-                return new SavedState(in);
-            }
-
-            public SavedState[] newArray(int size) {
-                return new SavedState[size];
-            }
-        };
-    }
-}