171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck/* 271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Copyright (C) 2013 The Android Open Source Project 371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * 471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Licensed under the Apache License, Version 2.0 (the "License"); 571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * you may not use this file except in compliance with the License. 671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * You may obtain a copy of the License at 771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * 871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * http://www.apache.org/licenses/LICENSE-2.0 971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * 1071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Unless required by applicable law or agreed to in writing, software 1171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * distributed under the License is distributed on an "AS IS" BASIS, 1271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * See the License for the specific language governing permissions and 1471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * limitations under the License. 1571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 1671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 1771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckpackage com.android.photos.views; 1871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 1971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.content.Context; 2071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.content.res.TypedArray; 2171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.database.DataSetObserver; 2271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.graphics.Canvas; 2371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.support.v4.view.MotionEventCompat; 2471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.support.v4.view.VelocityTrackerCompat; 2571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.support.v4.view.ViewCompat; 2671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.support.v4.widget.EdgeEffectCompat; 2771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.util.AttributeSet; 2871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.util.Log; 2971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.util.SparseArray; 3071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.view.MotionEvent; 3171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.view.VelocityTracker; 3271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.view.View; 3371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.view.ViewConfiguration; 3471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.view.ViewGroup; 3571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.widget.ListAdapter; 3671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport android.widget.OverScroller; 3771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 3871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckimport java.util.ArrayList; 3971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 4071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reckpublic class GalleryThumbnailView extends ViewGroup { 4171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 4271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public interface GalleryThumbnailAdapter extends ListAdapter { 4371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck /** 4471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * @param position Position to get the intrinsic aspect ratio for 4571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * @return width / height 4671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 4771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck float getIntrinsicAspectRatio(int position); 4871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 4971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 5071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private static final String TAG = "GalleryThumbnailView"; 5171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private static final float ASPECT_RATIO = (float) Math.sqrt(1.5f); 5271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private static final int LAND_UNITS = 2; 5371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private static final int PORT_UNITS = 3; 5471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 5571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private GalleryThumbnailAdapter mAdapter; 5671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 5771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private final RecycleBin mRecycler = new RecycleBin(); 5871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 5971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private final AdapterDataSetObserver mObserver = new AdapterDataSetObserver(); 6071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 6171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private boolean mDataChanged; 6271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mOldItemCount; 6371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mItemCount; 6471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private boolean mHasStableIds; 6571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 6671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mFirstPosition; 6771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 6871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private boolean mPopulating; 6971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private boolean mInLayout; 7071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 7171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mTouchSlop; 7271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mMaximumVelocity; 7371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mFlingVelocity; 7471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private float mLastTouchX; 7571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private float mTouchRemainderX; 7671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mActivePointerId; 7771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 7871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private static final int TOUCH_MODE_IDLE = 0; 7971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private static final int TOUCH_MODE_DRAGGING = 1; 8071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private static final int TOUCH_MODE_FLINGING = 2; 8171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 8271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mTouchMode; 8371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); 8471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private final OverScroller mScroller; 8571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 8671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private final EdgeEffectCompat mLeftEdge; 8771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private final EdgeEffectCompat mRightEdge; 8871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 8971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mLargeColumnWidth; 9071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mSmallColumnWidth; 9171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mLargeColumnUnitCount = 8; 9271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mSmallColumnUnitCount = 10; 9371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 9471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public GalleryThumbnailView(Context context) { 9571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck this(context, null); 9671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 9771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 9871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public GalleryThumbnailView(Context context, AttributeSet attrs) { 9971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck this(context, attrs, 0); 10071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 10171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 10271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public GalleryThumbnailView(Context context, AttributeSet attrs, int defStyle) { 10371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck super(context, attrs, defStyle); 10471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 10571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final ViewConfiguration vc = ViewConfiguration.get(context); 10671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchSlop = vc.getScaledTouchSlop(); 10771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mMaximumVelocity = vc.getScaledMaximumFlingVelocity(); 10871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mFlingVelocity = vc.getScaledMinimumFlingVelocity(); 10971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mScroller = new OverScroller(context); 11071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 11171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mLeftEdge = new EdgeEffectCompat(context); 11271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mRightEdge = new EdgeEffectCompat(context); 11371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck setWillNotDraw(false); 11471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck setClipToPadding(false); 11571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 11671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 11771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 11871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void requestLayout() { 11971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (!mPopulating) { 12071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck super.requestLayout(); 12171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 12271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 12371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 12471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 12571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 12671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int widthMode = MeasureSpec.getMode(widthMeasureSpec); 12771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int heightMode = MeasureSpec.getMode(heightMeasureSpec); 12871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int widthSize = MeasureSpec.getSize(widthMeasureSpec); 12971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int heightSize = MeasureSpec.getSize(heightMeasureSpec); 13071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 13171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (widthMode != MeasureSpec.EXACTLY) { 13271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Log.e(TAG, "onMeasure: must have an exact width or match_parent! " + 13371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck "Using fallback spec of EXACTLY " + widthSize); 13471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 13571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (heightMode != MeasureSpec.EXACTLY) { 13671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Log.e(TAG, "onMeasure: must have an exact height or match_parent! " + 13771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck "Using fallback spec of EXACTLY " + heightSize); 13871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 13971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 14071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck setMeasuredDimension(widthSize, heightSize); 14171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 14271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck float portSpaces = mLargeColumnUnitCount / PORT_UNITS; 14371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck float height = getMeasuredHeight() / portSpaces; 14471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mLargeColumnWidth = (int) (height / ASPECT_RATIO); 14571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck portSpaces++; 14671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck height = getMeasuredHeight() / portSpaces; 14771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mSmallColumnWidth = (int) (height / ASPECT_RATIO); 14871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 14971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 15071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 15171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck protected void onLayout(boolean changed, int l, int t, int r, int b) { 15271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mInLayout = true; 15371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck populate(); 15471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mInLayout = false; 15571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 15671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int width = r - l; 15771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int height = b - t; 15871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mLeftEdge.setSize(width, height); 15971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mRightEdge.setSize(width, height); 16071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 16171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 16271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private void populate() { 16371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (getWidth() == 0 || getHeight() == 0) { 16471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return; 16571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 16671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 16771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // TODO: Handle size changing 16871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// final int colCount = mColCount; 16971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// if (mItemTops == null || mItemTops.length != colCount) { 17071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// mItemTops = new int[colCount]; 17171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// mItemBottoms = new int[colCount]; 17271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// final int top = getPaddingTop(); 17371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// final int offset = top + Math.min(mRestoreOffset, 0); 17471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// Arrays.fill(mItemTops, offset); 17571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// Arrays.fill(mItemBottoms, offset); 17671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// mLayoutRecords.clear(); 17771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// if (mInLayout) { 17871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// removeAllViewsInLayout(); 17971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// } else { 18071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// removeAllViews(); 18171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// } 18271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// mRestoreOffset = 0; 18371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// } 18471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 18571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mPopulating = true; 18671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck layoutChildren(mDataChanged); 18771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck fillRight(mFirstPosition + getChildCount(), 0); 18871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck fillLeft(mFirstPosition - 1, 0); 18971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mPopulating = false; 19071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mDataChanged = false; 19171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 19271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 19371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final void layoutChildren(boolean queryAdapter) { 19471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// TODO 19571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// final int childCount = getChildCount(); 19671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// for (int i = 0; i < childCount; i++) { 19771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// View child = getChildAt(i); 19871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// 19971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// if (child.isLayoutRequested()) { 20071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// final int widthSpec = MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), MeasureSpec.EXACTLY); 20171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// final int heightSpec = MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY); 20271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// child.measure(widthSpec, heightSpec); 20371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// child.layout(child.getLeft(), child.getTop(), child.getRight(), child.getBottom()); 20471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// } 20571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// 20671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// int childTop = mItemBottoms[col] > Integer.MIN_VALUE ? 20771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// mItemBottoms[col] + mItemMargin : child.getTop(); 20871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// if (span > 1) { 20971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// int lowest = childTop; 21071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// for (int j = col + 1; j < col + span; j++) { 21171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// final int bottom = mItemBottoms[j] + mItemMargin; 21271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// if (bottom > lowest) { 21371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// lowest = bottom; 21471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// } 21571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// } 21671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// childTop = lowest; 21771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// } 21871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// final int childHeight = child.getMeasuredHeight(); 21971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// final int childBottom = childTop + childHeight; 22071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// final int childLeft = paddingLeft + col * (colWidth + itemMargin); 22171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// final int childRight = childLeft + child.getMeasuredWidth(); 22271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// child.layout(childLeft, childTop, childRight, childBottom); 22371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck// } 22471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 22571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 22671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck /** 22771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Obtain the view and add it to our list of children. The view can be made 22871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * fresh, converted from an unused view, or used as is if it was in the 22971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * recycle bin. 23071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * 23171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * @param startPosition Logical position in the list to start from 23271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * @param x Left or right edge of the view to add 23371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * @param forward If true, align left edge to x and increase position. 23471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * If false, align right edge to x and decrease position. 23571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * @return Number of views added 23671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 23771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int makeAndAddColumn(int startPosition, int x, boolean forward) { 23871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int columnWidth = mLargeColumnWidth; 23971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int addViews = 0; 24071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck for (int remaining = mLargeColumnUnitCount, i = 0; 24171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck remaining > 0 && startPosition + i >= 0 && startPosition + i < mItemCount; 24271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck i += forward ? 1 : -1, addViews++) { 24371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mAdapter.getIntrinsicAspectRatio(startPosition + i) >= 1f) { 24471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // landscape 24571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck remaining -= LAND_UNITS; 24671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 24771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // portrait 24871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck remaining -= PORT_UNITS; 24971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (remaining < 0) { 25071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck remaining += (mSmallColumnUnitCount - mLargeColumnUnitCount); 25171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck columnWidth = mSmallColumnWidth; 25271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 25371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 25471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 25571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int nextTop = 0; 25671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck for (int i = 0; i < addViews; i++) { 25771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int position = startPosition + (forward ? i : -i); 25871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck View child = obtainView(position, null); 25971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (child.getParent() != this) { 26071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mInLayout) { 26171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck addViewInLayout(child, forward ? -1 : 0, child.getLayoutParams()); 26271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 26371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck addView(child, forward ? -1 : 0); 26471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 26571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 26671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int heightSize = (int) (.5f + (mAdapter.getIntrinsicAspectRatio(position) >= 1f 26771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck ? columnWidth / ASPECT_RATIO 26871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck : columnWidth * ASPECT_RATIO)); 26971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int heightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); 27071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int widthSpec = MeasureSpec.makeMeasureSpec(columnWidth, MeasureSpec.EXACTLY); 27171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck child.measure(widthSpec, heightSpec); 27271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int childLeft = forward ? x : x - columnWidth; 27371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck child.layout(childLeft, nextTop, childLeft + columnWidth, nextTop + heightSize); 27471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck nextTop += heightSize; 27571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 27671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return addViews; 27771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 27871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 27971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 28071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public boolean onInterceptTouchEvent(MotionEvent ev) { 28171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mVelocityTracker.addMovement(ev); 28271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; 28371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck switch (action) { 28471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck case MotionEvent.ACTION_DOWN: 28571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mVelocityTracker.clear(); 28671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mScroller.abortAnimation(); 28771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mLastTouchX = ev.getX(); 28871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mActivePointerId = MotionEventCompat.getPointerId(ev, 0); 28971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchRemainderX = 0; 29071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mTouchMode == TOUCH_MODE_FLINGING) { 29171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // Catch! 29271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchMode = TOUCH_MODE_DRAGGING; 29371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return true; 29471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 29571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck break; 29671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 29771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck case MotionEvent.ACTION_MOVE: { 29871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId); 29971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (index < 0) { 30071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Log.e(TAG, "onInterceptTouchEvent could not find pointer with id " + 30171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mActivePointerId + " - did StaggeredGridView receive an inconsistent " + 30271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck "event stream?"); 30371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return false; 30471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 30571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final float x = MotionEventCompat.getX(ev, index); 30671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final float dx = x - mLastTouchX + mTouchRemainderX; 30771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int deltaY = (int) dx; 30871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchRemainderX = dx - deltaY; 30971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 31071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (Math.abs(dx) > mTouchSlop) { 31171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchMode = TOUCH_MODE_DRAGGING; 31271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return true; 31371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 31471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 31571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 31671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 31771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return false; 31871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 31971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 32071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 32171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public boolean onTouchEvent(MotionEvent ev) { 32271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mVelocityTracker.addMovement(ev); 32371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; 32471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck switch (action) { 32571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck case MotionEvent.ACTION_DOWN: 32671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mVelocityTracker.clear(); 32771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mScroller.abortAnimation(); 32871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mLastTouchX = ev.getX(); 32971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mActivePointerId = MotionEventCompat.getPointerId(ev, 0); 33071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchRemainderX = 0; 33171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck break; 33271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 33371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck case MotionEvent.ACTION_MOVE: { 33471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId); 33571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (index < 0) { 33671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Log.e(TAG, "onInterceptTouchEvent could not find pointer with id " + 33771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mActivePointerId + " - did StaggeredGridView receive an inconsistent " + 33871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck "event stream?"); 33971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return false; 34071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 34171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final float x = MotionEventCompat.getX(ev, index); 34271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final float dx = x - mLastTouchX + mTouchRemainderX; 34371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int deltaX = (int) dx; 34471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchRemainderX = dx - deltaX; 34571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 34671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (Math.abs(dx) > mTouchSlop) { 34771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchMode = TOUCH_MODE_DRAGGING; 34871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 34971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 35071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mTouchMode == TOUCH_MODE_DRAGGING) { 35171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mLastTouchX = x; 35271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 35371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (!trackMotionScroll(deltaX, true)) { 35471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // Break fling velocity if we impacted an edge. 35571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mVelocityTracker.clear(); 35671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 35771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 35871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } break; 35971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 36071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck case MotionEvent.ACTION_CANCEL: 36171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchMode = TOUCH_MODE_IDLE; 36271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck break; 36371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 36471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck case MotionEvent.ACTION_UP: { 36571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); 36671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final float velocity = VelocityTrackerCompat.getXVelocity(mVelocityTracker, 36771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mActivePointerId); 36871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (Math.abs(velocity) > mFlingVelocity) { // TODO 36971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchMode = TOUCH_MODE_FLINGING; 37071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mScroller.fling(0, 0, (int) velocity, 0, 37171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0); 37271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mLastTouchX = 0; 37371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck ViewCompat.postInvalidateOnAnimation(this); 37471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 37571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchMode = TOUCH_MODE_IDLE; 37671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 37771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 37871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } break; 37971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 38071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return true; 38171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 38271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 38371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck /** 38471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * 38571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * @param deltaX Pixels that content should move by 38671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * @return true if the movement completed, false if it was stopped prematurely. 38771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 38871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private boolean trackMotionScroll(int deltaX, boolean allowOverScroll) { 38971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final boolean contentFits = contentFits(); 39071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int allowOverhang = Math.abs(deltaX); 39171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 39271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int overScrolledBy; 39371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int movedBy; 39471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (!contentFits) { 39571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int overhang; 39671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final boolean up; 39771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mPopulating = true; 39871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (deltaX > 0) { 39971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck overhang = fillLeft(mFirstPosition - 1, allowOverhang); 40071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck up = true; 40171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 40271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck overhang = fillRight(mFirstPosition + getChildCount(), allowOverhang); 40371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck up = false; 40471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 40571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck movedBy = Math.min(overhang, allowOverhang); 40671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck offsetChildren(up ? movedBy : -movedBy); 40771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck recycleOffscreenViews(); 40871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mPopulating = false; 40971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck overScrolledBy = allowOverhang - overhang; 41071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 41171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck overScrolledBy = allowOverhang; 41271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck movedBy = 0; 41371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 41471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 41571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (allowOverScroll) { 41671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int overScrollMode = ViewCompat.getOverScrollMode(this); 41771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 41871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS || 41971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck (overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS && !contentFits)) { 42071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 42171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (overScrolledBy > 0) { 42271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck EdgeEffectCompat edge = deltaX > 0 ? mLeftEdge : mRightEdge; 42371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck edge.onPull((float) Math.abs(deltaX) / getWidth()); 42471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck ViewCompat.postInvalidateOnAnimation(this); 42571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 42671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 42771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 42871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 42971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return deltaX == 0 || movedBy != 0; 43071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 43171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 43271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck /** 43371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Important: this method will leave offscreen views attached if they 43471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * are required to maintain the invariant that child view with index i 43571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * is always the view corresponding to position mFirstPosition + i. 43671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 43771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private void recycleOffscreenViews() { 43871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int height = getHeight(); 43971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int clearAbove = 0; 44071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int clearBelow = height; 44171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck for (int i = getChildCount() - 1; i >= 0; i--) { 44271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final View child = getChildAt(i); 44371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (child.getTop() <= clearBelow) { 44471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // There may be other offscreen views, but we need to maintain 44571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // the invariant documented above. 44671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck break; 44771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 44871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 44971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mInLayout) { 45071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck removeViewsInLayout(i, 1); 45171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 45271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck removeViewAt(i); 45371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 45471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 45571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mRecycler.addScrap(child); 45671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 45771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 45871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck while (getChildCount() > 0) { 45971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final View child = getChildAt(0); 46071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (child.getBottom() >= clearAbove) { 46171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // There may be other offscreen views, but we need to maintain 46271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // the invariant documented above. 46371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck break; 46471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 46571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 46671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mInLayout) { 46771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck removeViewsInLayout(0, 1); 46871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 46971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck removeViewAt(0); 47071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 47171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 47271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mRecycler.addScrap(child); 47371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mFirstPosition++; 47471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 47571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 47671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 47771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final void offsetChildren(int offset) { 47871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int childCount = getChildCount(); 47971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck for (int i = 0; i < childCount; i++) { 48071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final View child = getChildAt(i); 48171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck child.layout(child.getLeft() + offset, child.getTop(), 48271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck child.getRight() + offset, child.getBottom()); 48371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 48471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 48571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 48671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private boolean contentFits() { 48771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int childCount = getChildCount(); 48871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (childCount == 0) return true; 48971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (childCount != mItemCount) return false; 49071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 49171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return getChildAt(0).getLeft() >= getPaddingLeft() && 49271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck getChildAt(childCount - 1).getRight() <= getWidth() - getPaddingRight(); 49371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 49471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 49571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private void recycleAllViews() { 49671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck for (int i = 0; i < getChildCount(); i++) { 49771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mRecycler.addScrap(getChildAt(i)); 49871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 49971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 50071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mInLayout) { 50171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck removeAllViewsInLayout(); 50271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 50371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck removeAllViews(); 50471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 50571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 50671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 50771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int fillRight(int pos, int overhang) { 50871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int end = (getRight() - getLeft()) + overhang; 50971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 51071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int nextLeft = getChildCount() == 0 ? 0 : getChildAt(getChildCount() - 1).getRight(); 51171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck while (nextLeft < end && pos < mItemCount) { 51271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck pos += makeAndAddColumn(pos, nextLeft, true); 51371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck nextLeft = getChildAt(getChildCount() - 1).getRight(); 51471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 51571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int gridRight = getWidth() - getPaddingRight(); 51671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return getChildAt(getChildCount() - 1).getRight() - gridRight; 51771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 51871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 51971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int fillLeft(int pos, int overhang) { 52071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int end = getPaddingLeft() - overhang; 52171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 52271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int nextRight = getChildAt(0).getLeft(); 52371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck while (nextRight > end && pos >= 0) { 52471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck pos -= makeAndAddColumn(pos, nextRight, false); 52571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck nextRight = getChildAt(0).getLeft(); 52671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 52771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 52871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mFirstPosition = pos + 1; 52971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return getPaddingLeft() - getChildAt(0).getLeft(); 53071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 53171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 53271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 53371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void computeScroll() { 53471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mScroller.computeScrollOffset()) { 53571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int x = mScroller.getCurrX(); 53671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int dx = (int) (x - mLastTouchX); 53771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mLastTouchX = x; 53871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final boolean stopped = !trackMotionScroll(dx, false); 53971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 54071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (!stopped && !mScroller.isFinished()) { 54171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck ViewCompat.postInvalidateOnAnimation(this); 54271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 54371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (stopped) { 54471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int overScrollMode = ViewCompat.getOverScrollMode(this); 54571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (overScrollMode != ViewCompat.OVER_SCROLL_NEVER) { 54671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final EdgeEffectCompat edge; 54771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (dx > 0) { 54871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck edge = mLeftEdge; 54971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 55071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck edge = mRightEdge; 55171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 55271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck edge.onAbsorb(Math.abs((int) mScroller.getCurrVelocity())); 55371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck ViewCompat.postInvalidateOnAnimation(this); 55471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 55571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mScroller.abortAnimation(); 55671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 55771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTouchMode = TOUCH_MODE_IDLE; 55871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 55971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 56071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 56171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 56271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 56371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void draw(Canvas canvas) { 56471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck super.draw(canvas); 56571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 56671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (!mLeftEdge.isFinished()) { 56771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int restoreCount = canvas.save(); 56871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int height = getHeight() - getPaddingTop() - getPaddingBottom(); 56971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 57071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck canvas.rotate(270); 57171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck canvas.translate(-height + getPaddingTop(), 0); 57271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mLeftEdge.setSize(height, getWidth()); 57371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mLeftEdge.draw(canvas)) { 57471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck postInvalidateOnAnimation(); 57571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 57671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck canvas.restoreToCount(restoreCount); 57771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 57871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (!mRightEdge.isFinished()) { 57971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int restoreCount = canvas.save(); 58071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int width = getWidth(); 58171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int height = getHeight() - getPaddingTop() - getPaddingBottom(); 58271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 58371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck canvas.rotate(90); 58471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck canvas.translate(-getPaddingTop(), width); 58571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mRightEdge.setSize(height, width); 58671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mRightEdge.draw(canvas)) { 58771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck postInvalidateOnAnimation(); 58871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 58971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck canvas.restoreToCount(restoreCount); 59071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 59171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 59271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 59371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck /** 59471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Obtain a populated view from the adapter. If optScrap is non-null and is not 59571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * reused it will be placed in the recycle bin. 59671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * 59771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * @param position position to get view for 59871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * @param optScrap Optional scrap view; will be reused if possible 59971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * @return A new view, a recycled view from mRecycler, or optScrap 60071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 60171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private final View obtainView(int position, View optScrap) { 60271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck View view = mRecycler.getTransientStateView(position); 60371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (view != null) { 60471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return view; 60571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 60671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 60771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // Reuse optScrap if it's of the right type (and not null) 60871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int optType = optScrap != null ? 60971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck ((LayoutParams) optScrap.getLayoutParams()).viewType : -1; 61071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int positionViewType = mAdapter.getItemViewType(position); 61171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final View scrap = optType == positionViewType ? 61271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck optScrap : mRecycler.getScrapView(positionViewType); 61371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 61471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck view = mAdapter.getView(position, scrap, this); 61571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 61671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (view != scrap && scrap != null) { 61771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // The adapter didn't use it; put it back. 61871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mRecycler.addScrap(scrap); 61971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 62071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 62171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck ViewGroup.LayoutParams lp = view.getLayoutParams(); 62271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 62371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (view.getParent() != this) { 62471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (lp == null) { 62571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck lp = generateDefaultLayoutParams(); 62671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else if (!checkLayoutParams(lp)) { 62771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck lp = generateLayoutParams(lp); 62871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 62971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck view.setLayoutParams(lp); 63071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 63171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 63271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final LayoutParams sglp = (LayoutParams) lp; 63371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck sglp.position = position; 63471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck sglp.viewType = positionViewType; 63571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 63671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return view; 63771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 63871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 63971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public GalleryThumbnailAdapter getAdapter() { 64071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return mAdapter; 64171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 64271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 64371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void setAdapter(GalleryThumbnailAdapter adapter) { 64471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mAdapter != null) { 64571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mAdapter.unregisterDataSetObserver(mObserver); 64671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 64771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // TODO: If the new adapter says that there are stable IDs, remove certain layout records 64871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // and onscreen views if they have changed instead of removing all of the state here. 64971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck clearAllState(); 65071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mAdapter = adapter; 65171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mDataChanged = true; 65271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mOldItemCount = mItemCount = adapter != null ? adapter.getCount() : 0; 65371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (adapter != null) { 65471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck adapter.registerDataSetObserver(mObserver); 65571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mRecycler.setViewTypeCount(adapter.getViewTypeCount()); 65671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mHasStableIds = adapter.hasStableIds(); 65771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } else { 65871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mHasStableIds = false; 65971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 66071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck populate(); 66171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 66271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 66371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck /** 66471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Clear all state because the grid will be used for a completely different set of data. 66571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 66671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private void clearAllState() { 66771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // Clear all layout records and views 66871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck removeAllViews(); 66971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 67071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // Reset to the top of the grid 67171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mFirstPosition = 0; 67271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 67371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // Clear recycler because there could be different view types now 67471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mRecycler.clear(); 67571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 67671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 67771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 67871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck protected LayoutParams generateDefaultLayoutParams() { 67971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return new LayoutParams(LayoutParams.WRAP_CONTENT); 68071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 68171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 68271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 68371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { 68471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return new LayoutParams(lp); 68571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 68671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 68771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 68871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck protected boolean checkLayoutParams(ViewGroup.LayoutParams lp) { 68971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return lp instanceof LayoutParams; 69071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 69171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 69271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 69371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { 69471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return new LayoutParams(getContext(), attrs); 69571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 69671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 69771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public static class LayoutParams extends ViewGroup.LayoutParams { 69871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private static final int[] LAYOUT_ATTRS = new int[] { 69971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck android.R.attr.layout_span 70071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck }; 70171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 70271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private static final int SPAN_INDEX = 0; 70371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 70471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck /** 70571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * The number of columns this item should span 70671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 70771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public int span = 1; 70871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 70971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck /** 71071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Item position this view represents 71171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 71271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int position; 71371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 71471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck /** 71571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * Type of this view as reported by the adapter 71671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 71771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int viewType; 71871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 71971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck /** 72071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * The column this view is occupying 72171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 72271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck int column; 72371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 72471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck /** 72571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck * The stable ID of the item this view displays 72671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck */ 72771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck long id = -1; 72871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 72971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public LayoutParams(int height) { 73071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck super(MATCH_PARENT, height); 73171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 73271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (this.height == MATCH_PARENT) { 73371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Log.w(TAG, "Constructing LayoutParams with height MATCH_PARENT - " + 73471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck "impossible! Falling back to WRAP_CONTENT"); 73571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck this.height = WRAP_CONTENT; 73671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 73771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 73871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 73971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public LayoutParams(Context c, AttributeSet attrs) { 74071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck super(c, attrs); 74171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 74271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (this.width != MATCH_PARENT) { 74371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Log.w(TAG, "Inflation setting LayoutParams width to " + this.width + 74471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck " - must be MATCH_PARENT"); 74571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck this.width = MATCH_PARENT; 74671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 74771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (this.height == MATCH_PARENT) { 74871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Log.w(TAG, "Inflation setting LayoutParams height to MATCH_PARENT - " + 74971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck "impossible! Falling back to WRAP_CONTENT"); 75071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck this.height = WRAP_CONTENT; 75171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 75271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 75371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck TypedArray a = c.obtainStyledAttributes(attrs, LAYOUT_ATTRS); 75471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck span = a.getInteger(SPAN_INDEX, 1); 75571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck a.recycle(); 75671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 75771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 75871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public LayoutParams(ViewGroup.LayoutParams other) { 75971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck super(other); 76071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 76171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (this.width != MATCH_PARENT) { 76271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Log.w(TAG, "Constructing LayoutParams with width " + this.width + 76371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck " - must be MATCH_PARENT"); 76471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck this.width = MATCH_PARENT; 76571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 76671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (this.height == MATCH_PARENT) { 76771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck Log.w(TAG, "Constructing LayoutParams with height MATCH_PARENT - " + 76871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck "impossible! Falling back to WRAP_CONTENT"); 76971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck this.height = WRAP_CONTENT; 77071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 77171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 77271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 77371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 77471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private class RecycleBin { 77571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private ArrayList<View>[] mScrapViews; 77671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mViewTypeCount; 77771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private int mMaxScrap; 77871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 77971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private SparseArray<View> mTransientStateViews; 78071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 78171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void setViewTypeCount(int viewTypeCount) { 78271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (viewTypeCount < 1) { 78371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck throw new IllegalArgumentException("Must have at least one view type (" + 78471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck viewTypeCount + " types reported)"); 78571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 78671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (viewTypeCount == mViewTypeCount) { 78771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return; 78871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 78971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 79071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck ArrayList<View>[] scrapViews = new ArrayList[viewTypeCount]; 79171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck for (int i = 0; i < viewTypeCount; i++) { 79271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck scrapViews[i] = new ArrayList<View>(); 79371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 79471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mViewTypeCount = viewTypeCount; 79571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mScrapViews = scrapViews; 79671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 79771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 79871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void clear() { 79971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int typeCount = mViewTypeCount; 80071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck for (int i = 0; i < typeCount; i++) { 80171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mScrapViews[i].clear(); 80271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 80371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mTransientStateViews != null) { 80471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTransientStateViews.clear(); 80571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 80671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 80771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 80871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void clearTransientViews() { 80971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mTransientStateViews != null) { 81071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTransientStateViews.clear(); 81171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 81271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 81371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 81471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void addScrap(View v) { 81571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final LayoutParams lp = (LayoutParams) v.getLayoutParams(); 81671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (ViewCompat.hasTransientState(v)) { 81771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mTransientStateViews == null) { 81871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTransientStateViews = new SparseArray<View>(); 81971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 82071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTransientStateViews.put(lp.position, v); 82171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return; 82271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 82371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 82471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int childCount = getChildCount(); 82571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (childCount > mMaxScrap) { 82671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mMaxScrap = childCount; 82771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 82871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 82971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck ArrayList<View> scrap = mScrapViews[lp.viewType]; 83071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (scrap.size() < mMaxScrap) { 83171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck scrap.add(v); 83271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 83371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 83471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 83571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public View getTransientStateView(int position) { 83671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (mTransientStateViews == null) { 83771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return null; 83871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 83971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 84071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final View result = mTransientStateViews.get(position); 84171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (result != null) { 84271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mTransientStateViews.remove(position); 84371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 84471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return result; 84571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 84671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 84771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public View getScrapView(int type) { 84871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck ArrayList<View> scrap = mScrapViews[type]; 84971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (scrap.isEmpty()) { 85071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return null; 85171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 85271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 85371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final int index = scrap.size() - 1; 85471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck final View result = scrap.get(index); 85571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck scrap.remove(index); 85671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck return result; 85771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 85871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 85971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 86071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck private class AdapterDataSetObserver extends DataSetObserver { 86171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 86271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void onChanged() { 86371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mDataChanged = true; 86471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mOldItemCount = mItemCount; 86571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mItemCount = mAdapter.getCount(); 86671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 86771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // TODO: Consider matching these back up if we have stable IDs. 86871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck mRecycler.clearTransientViews(); 86971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 87071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck if (!mHasStableIds) { 87171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck recycleAllViews(); 87271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 87371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 87471bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // TODO: consider repopulating in a deferred runnable instead 87571bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck // (so that successive changes may still be batched) 87671bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck requestLayout(); 87771bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 87871bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck 87971bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck @Override 88071bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck public void onInvalidated() { 88171bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 88271bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck } 88371bfefaf9029df26ba4c6e4077c4e3e2f259634fJohn Reck} 884