GridView.java revision aebd28f729fa28016d70551d0372ab7fcd56ee1a
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
20499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.content.Intent;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent;
26499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.view.SoundEffectConstants;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
288d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sappersteinimport android.view.ViewDebug;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup;
308a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent;
318a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.animation.GridLayoutAnimationController;
33499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.widget.RemoteViews.RemoteView;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A view that shows items in two-dimensional scrolling grid. The items in the
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * grid come from the {@link ListAdapter} associated with this view.
3941ec65355bd6ded652769725b276d47c54a0d913Scott Main *
4041ec65355bd6ded652769725b276d47c54a0d913Scott Main * <p>See the <a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Grid
4141ec65355bd6ded652769725b276d47c54a0d913Scott Main * View tutorial</a>.</p>
4284c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy *
4384c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_horizontalSpacing
4484c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_verticalSpacing
4584c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_stretchMode
4684c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_columnWidth
4784c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_numColumns
4884c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_gravity
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
50499cb9f516062b654952d282f211bee44c31a3c2Winson Chung@RemoteView
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GridView extends AbsListView {
5284c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy    /**
5384c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     * Disables stretching.
5484c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     *
5584c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     * @see #setStretchMode(int)
5684c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     */
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int NO_STRETCH = 0;
5884c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy    /**
5984c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     * Stretches the spacing between columns.
6084c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     *
6184c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     * @see #setStretchMode(int)
6284c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     */
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int STRETCH_SPACING = 1;
6484c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy    /**
6584c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     * Stretches columns.
6684c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     *
6784c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     * @see #setStretchMode(int)
6884c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     */
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int STRETCH_COLUMN_WIDTH = 2;
7084c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy    /**
7184c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     * Stretches the spacing between columns. The spacing is uniform.
7284c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     *
7384c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     * @see #setStretchMode(int)
7484c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     */
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int STRETCH_SPACING_UNIFORM = 3;
7684c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy
7784c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy    /**
7884c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     * Creates as many columns as can fit on screen.
7984c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     *
8084c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     * @see #setNumColumns(int)
8184c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy     */
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int AUTO_FIT = -1;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNumColumns = AUTO_FIT;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mHorizontalSpacing = 0;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mRequestedHorizontalSpacing;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mVerticalSpacing = 0;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mStretchMode = STRETCH_COLUMN_WIDTH;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mColumnWidth;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mRequestedColumnWidth;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mRequestedNumColumns;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View mReferenceView = null;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View mReferenceViewInSelectedRow = null;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mGravity = Gravity.LEFT;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Rect mTempRect = new Rect();
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public GridView(Context context) {
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context);
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public GridView(Context context, AttributeSet attrs) {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(context, attrs, com.android.internal.R.attr.gridViewStyle);
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public GridView(Context context, AttributeSet attrs, int defStyle) {
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super(context, attrs, defStyle);
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        TypedArray a = context.obtainStyledAttributes(attrs,
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.styleable.GridView, defStyle, 0);
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int hSpacing = a.getDimensionPixelOffset(
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.styleable.GridView_horizontalSpacing, 0);
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setHorizontalSpacing(hSpacing);
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int vSpacing = a.getDimensionPixelOffset(
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                com.android.internal.R.styleable.GridView_verticalSpacing, 0);
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setVerticalSpacing(vSpacing);
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int index = a.getInt(com.android.internal.R.styleable.GridView_stretchMode, STRETCH_COLUMN_WIDTH);
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (index >= 0) {
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setStretchMode(index);
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int columnWidth = a.getDimensionPixelOffset(com.android.internal.R.styleable.GridView_columnWidth, -1);
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (columnWidth > 0) {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setColumnWidth(columnWidth);
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int numColumns = a.getInt(com.android.internal.R.styleable.GridView_numColumns, 1);
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setNumColumns(numColumns);
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        index = a.getInt(com.android.internal.R.styleable.GridView_gravity, -1);
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (index >= 0) {
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setGravity(index);
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        a.recycle();
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public ListAdapter getAdapter() {
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mAdapter;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
150499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     * Sets up this AbsListView to use a remote views adapter which connects to a RemoteViewsService
151499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     * through the specified intent.
152499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     * @param intent the intent used to identify the RemoteViewsService for the adapter to connect to.
153499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     */
154499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    @android.view.RemotableViewMethod
155499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    public void setRemoteViewsAdapter(Intent intent) {
156499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        super.setRemoteViewsAdapter(intent);
157499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    }
158499cb9f516062b654952d282f211bee44c31a3c2Winson Chung
159499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    /**
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the data behind this GridView.
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param adapter the adapter providing the grid's data
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setAdapter(ListAdapter adapter) {
166df36b0579e1e550de3d66a20362717e49b23235cRomain Guy        if (mAdapter != null && mDataSetObserver != null) {
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAdapter.unregisterDataSetObserver(mDataSetObserver);
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        resetList();
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mRecycler.clear();
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mAdapter = adapter;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOldSelectedPosition = INVALID_POSITION;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOldSelectedRowId = INVALID_ROW_ID;
176f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell
177f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell        // AbsListView#setAdapter will update choice mode states.
178f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell        super.setAdapter(adapter);
179f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mAdapter != null) {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mOldItemCount = mItemCount;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mItemCount = mAdapter.getCount();
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDataChanged = true;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            checkFocus();
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDataSetObserver = new AdapterDataSetObserver();
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mAdapter.registerDataSetObserver(mDataSetObserver);
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int position;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mStackFromBottom) {
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                position = lookForSelectablePosition(mItemCount - 1, false);
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                position = lookForSelectablePosition(0, true);
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setSelectedPositionInt(position);
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setNextSelectedPositionInt(position);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            checkSelectionChanged();
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            checkFocus();
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Nothing selected
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            checkSelectionChanged();
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        requestLayout();
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int lookForSelectablePosition(int position, boolean lookDown) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ListAdapter adapter = mAdapter;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (adapter == null || isInTouchMode()) {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return INVALID_POSITION;
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (position < 0 || position >= mItemCount) {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return INVALID_POSITION;
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return position;
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@inheritDoc}
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void fillGap(boolean down) {
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int numColumns = mNumColumns;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int verticalSpacing = mVerticalSpacing;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int count = getChildCount();
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (down) {
2338c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell            int paddingTop = 0;
2348c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell            if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
2358c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell                paddingTop = getListPaddingTop();
2368c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell            }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int startOffset = count > 0 ?
2388c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell                    getChildAt(count - 1).getBottom() + verticalSpacing : paddingTop;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int position = mFirstPosition + count;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mStackFromBottom) {
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                position += numColumns - 1;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillDown(position, startOffset);
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            correctTooHigh(numColumns, verticalSpacing, getChildCount());
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2468c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell            int paddingBottom = 0;
2478c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell            if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
2488c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell                paddingBottom = getListPaddingBottom();
2498c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell            }
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int startOffset = count > 0 ?
2518c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell                    getChildAt(0).getTop() - verticalSpacing : getHeight() - paddingBottom;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int position = mFirstPosition;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mStackFromBottom) {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                position -= numColumns;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                position--;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillUp(position, startOffset);
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            correctTooLow(numColumns, verticalSpacing, getChildCount());
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fills the list from pos down to the end of the list view.
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param pos The first position to put in the list
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param nextTop The location where the top of the item associated with pos
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        should be drawn
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The view that is currently selected, if it happens to be in the
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         range that we draw.
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View fillDown(int pos, int nextTop) {
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View selectedView = null;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2778c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell        int end = (mBottom - mTop);
2788c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell        if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
2798c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell            end -= mListPadding.bottom;
2808c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell        }
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (nextTop < end && pos < mItemCount) {
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View temp = makeRow(pos, nextTop, true);
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (temp != null) {
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                selectedView = temp;
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2888bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy            // mReferenceView will change with each call to makeRow()
2898bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy            // do not cache in a local variable outside of this loop
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            nextTop = mReferenceView.getBottom() + mVerticalSpacing;
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pos += mNumColumns;
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
295b967392e0170af8cfd8053fd43fcdf8c46f703e9Adam Cohen        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return selectedView;
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View makeRow(int startPos, int y, boolean flow) {
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int columnWidth = mColumnWidth;
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int horizontalSpacing = mHorizontalSpacing;
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int last;
3048bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy        int nextLeft = mListPadding.left +
3058bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy                ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0);
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            last = Math.min(startPos + mNumColumns, mItemCount);
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            last = startPos + 1;
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startPos = Math.max(0, startPos - mNumColumns + 1);
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (last - startPos < mNumColumns) {
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nextLeft += (mNumColumns - (last - startPos)) * (columnWidth + horizontalSpacing);
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View selectedView = null;
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean hasFocus = shouldShowSelector();
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean inClick = touchModeDrawsInPressedState();
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int selectedPosition = mSelectedPosition;
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3248bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy        View child = null;
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int pos = startPos; pos < last; pos++) {
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // is this the selected item?
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean selected = pos == selectedPosition;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // does the list view have focus or contain focus
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int where = flow ? -1 : pos - startPos;
3318bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy            child = makeAndAddView(pos, y, flow, nextLeft, selected, where);
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            nextLeft += columnWidth;
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pos < last - 1) {
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                nextLeft += horizontalSpacing;
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (selected && (hasFocus || inClick)) {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                selectedView = child;
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3438bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy        mReferenceView = child;
3448bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (selectedView != null) {
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mReferenceViewInSelectedRow = mReferenceView;
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return selectedView;
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fills the list from pos up to the top of the list view.
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param pos The first position to put in the list
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param nextBottom The location where the bottom of the item associated
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        with pos should be drawn
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The view that is currently selected
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View fillUp(int pos, int nextBottom) {
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View selectedView = null;
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3658c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell        int end = 0;
3668c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell        if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) {
3678c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell            end = mListPadding.top;
3688c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell        }
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        while (nextBottom > end && pos >= 0) {
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View temp = makeRow(pos, nextBottom, false);
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (temp != null) {
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                selectedView = temp;
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            nextBottom = mReferenceView.getTop() - mVerticalSpacing;
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFirstPosition = pos;
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pos -= mNumColumns;
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStackFromBottom) {
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFirstPosition = Math.max(0, pos + 1);
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
388b967392e0170af8cfd8053fd43fcdf8c46f703e9Adam Cohen        setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return selectedView;
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fills the list from top to bottom, starting with mFirstPosition
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param nextTop The location where the top of the first item should be
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        drawn
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The view that is currently selected
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View fillFromTop(int nextTop) {
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFirstPosition = Math.min(mFirstPosition, mSelectedPosition);
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFirstPosition = Math.min(mFirstPosition, mItemCount - 1);
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFirstPosition < 0) {
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFirstPosition = 0;
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFirstPosition -= mFirstPosition % mNumColumns;
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return fillDown(mFirstPosition, nextTop);
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View fillFromBottom(int lastPosition, int nextBottom) {
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lastPosition = Math.max(lastPosition, mSelectedPosition);
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lastPosition = Math.min(lastPosition, mItemCount - 1);
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int invertedPosition = mItemCount - 1 - lastPosition;
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lastPosition = mItemCount - 1 - (invertedPosition - (invertedPosition % mNumColumns));
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return fillUp(lastPosition, nextBottom);
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View fillSelection(int childrenTop, int childrenBottom) {
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int selectedPosition = reconcileSelectedPosition();
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int numColumns = mNumColumns;
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int verticalSpacing = mVerticalSpacing;
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int rowStart;
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int rowEnd = -1;
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowStart = selectedPosition - (selectedPosition % numColumns);
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int invertedSelection = mItemCount - 1 - selectedPosition;
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns));
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowStart = Math.max(0, rowEnd - numColumns + 1);
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int fadingEdgeLength = getVerticalFadingEdgeLength();
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength, rowStart);
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final View sel = makeRow(mStackFromBottom ? rowEnd : rowStart, topSelectionPixel, true);
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFirstPosition = rowStart;
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final View referenceView = mReferenceView;
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillDown(rowStart + numColumns, referenceView.getBottom() + verticalSpacing);
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pinToBottom(childrenBottom);
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillUp(rowStart - numColumns, referenceView.getTop() - verticalSpacing);
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            adjustViewsUpOrDown();
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int bottomSelectionPixel = getBottomSelectionPixel(childrenBottom,
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fadingEdgeLength, numColumns, rowStart);
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int offset = bottomSelectionPixel - referenceView.getBottom();
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            offsetChildrenTopAndBottom(offset);
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillUp(rowStart - 1, referenceView.getTop() - verticalSpacing);
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pinToTop(childrenTop);
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillDown(rowEnd + numColumns, referenceView.getBottom() + verticalSpacing);
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            adjustViewsUpOrDown();
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sel;
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void pinToTop(int childrenTop) {
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFirstPosition == 0) {
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int top = getChildAt(0).getTop();
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int offset = childrenTop - top;
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (offset < 0) {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                offsetChildrenTopAndBottom(offset);
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void pinToBottom(int childrenBottom) {
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int count = getChildCount();
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFirstPosition + count == mItemCount) {
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int bottom = getChildAt(count - 1).getBottom();
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int offset = childrenBottom - bottom;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (offset > 0) {
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                offsetChildrenTopAndBottom(offset);
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int findMotionRow(int y) {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int childCount = getChildCount();
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (childCount > 0) {
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int numColumns = mNumColumns;
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mStackFromBottom) {
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i = 0; i < childCount; i += numColumns) {
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (y <= getChildAt(i).getBottom()) {
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return mFirstPosition + i;
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i = childCount - 1; i >= 0; i -= numColumns) {
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (y >= getChildAt(i).getTop()) {
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return mFirstPosition + i;
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return INVALID_POSITION;
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Layout during a scroll that results from tracking motion events. Places
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * the mMotionPosition view at the offset specified by mMotionViewTop, and
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * then build surrounding views from there.
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param position the position at which to start filling
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param top the top of the view at that position
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The selected view, or null if the selected view is outside the
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         visible area.
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View fillSpecific(int position, int top) {
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int numColumns = mNumColumns;
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int motionRowStart;
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int motionRowEnd = -1;
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            motionRowStart = position - (position % numColumns);
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int invertedSelection = mItemCount - 1 - position;
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            motionRowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns));
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            motionRowStart = Math.max(0, motionRowEnd - numColumns + 1);
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final View temp = makeRow(mStackFromBottom ? motionRowEnd : motionRowStart, top, true);
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Possibly changed again in fillUp if we add rows above this one.
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFirstPosition = motionRowStart;
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final View referenceView = mReferenceView;
5398bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy        // We didn't have anything to layout, bail out
5408bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy        if (referenceView == null) {
5418bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy            return null;
5428bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy        }
5438bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int verticalSpacing = mVerticalSpacing;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View above;
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View below;
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            above = fillUp(motionRowStart - numColumns, referenceView.getTop() - verticalSpacing);
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            adjustViewsUpOrDown();
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            below = fillDown(motionRowStart + numColumns, referenceView.getBottom() + verticalSpacing);
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Check if we have dragged the bottom of the grid too high
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int childCount = getChildCount();
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (childCount > 0) {
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                correctTooHigh(numColumns, verticalSpacing, childCount);
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            below = fillDown(motionRowEnd + numColumns, referenceView.getBottom() + verticalSpacing);
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            adjustViewsUpOrDown();
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            above = fillUp(motionRowStart - 1, referenceView.getTop() - verticalSpacing);
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Check if we have dragged the bottom of the grid too high
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int childCount = getChildCount();
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (childCount > 0) {
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                correctTooLow(numColumns, verticalSpacing, childCount);
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (temp != null) {
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return temp;
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (above != null) {
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return above;
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return below;
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void correctTooHigh(int numColumns, int verticalSpacing, int childCount) {
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // First see if the last item is visible
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int lastPosition = mFirstPosition + childCount - 1;
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (lastPosition == mItemCount - 1 && childCount > 0) {
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Get the last child ...
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final View lastChild = getChildAt(childCount - 1);
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ... and its bottom edge
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int lastBottom = lastChild.getBottom();
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This is bottom of our drawable area
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int end = (mBottom - mTop) - mListPadding.bottom;
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This is how far the bottom edge of the last view is from the bottom of the
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // drawable area
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int bottomOffset = end - lastBottom;
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final View firstChild = getChildAt(0);
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int firstTop = firstChild.getTop();
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Make sure we are 1) Too high, and 2) Either there are more rows above the
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // first row or the first row is scrolled off the top of the drawable area
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (bottomOffset > 0 && (mFirstPosition > 0 || firstTop < mListPadding.top))  {
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFirstPosition == 0) {
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Don't pull the top too far down
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    bottomOffset = Math.min(bottomOffset, mListPadding.top - firstTop);
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Move everything down
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                offsetChildrenTopAndBottom(bottomOffset);
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFirstPosition > 0) {
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Fill the gap that was opened above mFirstPosition with more rows, if
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // possible
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fillUp(mFirstPosition - (mStackFromBottom ? 1 : numColumns),
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            firstChild.getTop() - verticalSpacing);
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Close up the remaining gap
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    adjustViewsUpOrDown();
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void correctTooLow(int numColumns, int verticalSpacing, int childCount) {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFirstPosition == 0 && childCount > 0) {
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Get the first child ...
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final View firstChild = getChildAt(0);
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ... and its top edge
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int firstTop = firstChild.getTop();
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This is top of our drawable area
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int start = mListPadding.top;
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This is bottom of our drawable area
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int end = (mBottom - mTop) - mListPadding.bottom;
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // This is how far the top edge of the first view is from the top of the
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // drawable area
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int topOffset = firstTop - start;
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final View lastChild = getChildAt(childCount - 1);
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int lastBottom = lastChild.getBottom();
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int lastPosition = mFirstPosition + childCount - 1;
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Make sure we are 1) Too low, and 2) Either there are more rows below the
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // last row or the last row is scrolled off the bottom of the drawable area
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (topOffset > 0 && (lastPosition < mItemCount - 1 || lastBottom > end))  {
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (lastPosition == mItemCount - 1 ) {
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Don't pull the bottom too far up
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    topOffset = Math.min(topOffset, lastBottom - end);
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Move everything up
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                offsetChildrenTopAndBottom(-topOffset);
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (lastPosition < mItemCount - 1) {
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Fill the gap that was opened below the last position with more rows, if
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // possible
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fillDown(lastPosition + (!mStackFromBottom ? 1 : numColumns),
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            lastChild.getBottom() + verticalSpacing);
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Close up the remaining gap
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    adjustViewsUpOrDown();
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fills the grid based on positioning the new selection at a specific
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * location. The selection may be moved so that it does not intersect the
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * faded edges. The grid is then filled upwards and downwards from there.
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selectedTop Where the selected item should be
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childrenTop Where to start drawing children
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childrenBottom Last pixel where children can be drawn
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The view that currently has selection
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View fillFromSelection(int selectedTop, int childrenTop, int childrenBottom) {
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int fadingEdgeLength = getVerticalFadingEdgeLength();
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int selectedPosition = mSelectedPosition;
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int numColumns = mNumColumns;
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int verticalSpacing = mVerticalSpacing;
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int rowStart;
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int rowEnd = -1;
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowStart = selectedPosition - (selectedPosition % numColumns);
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int invertedSelection = mItemCount - 1 - selectedPosition;
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns));
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowStart = Math.max(0, rowEnd - numColumns + 1);
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View sel;
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View referenceView;
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength, rowStart);
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int bottomSelectionPixel = getBottomSelectionPixel(childrenBottom, fadingEdgeLength,
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                numColumns, rowStart);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sel = makeRow(mStackFromBottom ? rowEnd : rowStart, selectedTop, true);
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Possibly changed again in fillUp if we add rows above this one.
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFirstPosition = rowStart;
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        referenceView = mReferenceView;
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        adjustForTopFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel);
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        adjustForBottomFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel);
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillUp(rowStart - numColumns, referenceView.getTop() - verticalSpacing);
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            adjustViewsUpOrDown();
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillDown(rowStart + numColumns, referenceView.getBottom() + verticalSpacing);
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillDown(rowEnd + numColumns, referenceView.getBottom() + verticalSpacing);
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            adjustViewsUpOrDown();
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillUp(rowStart - 1, referenceView.getTop() - verticalSpacing);
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sel;
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Calculate the bottom-most pixel we can draw the selection into
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childrenBottom Bottom pixel were children can be drawn
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param fadingEdgeLength Length of the fading edge in pixels, if present
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param numColumns Number of columns in the grid
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rowStart The start of the row that will contain the selection
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The bottom-most pixel we can draw the selection into
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getBottomSelectionPixel(int childrenBottom, int fadingEdgeLength,
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int numColumns, int rowStart) {
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Last pixel we can draw the selection into
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int bottomSelectionPixel = childrenBottom;
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (rowStart + numColumns - 1 < mItemCount - 1) {
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            bottomSelectionPixel -= fadingEdgeLength;
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return bottomSelectionPixel;
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Calculate the top-most pixel we can draw the selection into
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childrenTop Top pixel were children can be drawn
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param fadingEdgeLength Length of the fading edge in pixels, if present
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param rowStart The start of the row that will contain the selection
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The top-most pixel we can draw the selection into
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getTopSelectionPixel(int childrenTop, int fadingEdgeLength, int rowStart) {
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // first pixel we can draw the selection into
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int topSelectionPixel = childrenTop;
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (rowStart > 0) {
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            topSelectionPixel += fadingEdgeLength;
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return topSelectionPixel;
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Move all views upwards so the selected row does not interesect the bottom
7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fading edge (if necessary).
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childInSelectedRow A child in the row that contains the selection
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param topSelectionPixel The topmost pixel we can draw the selection into
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param bottomSelectionPixel The bottommost pixel we can draw the
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        selection into
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void adjustForBottomFadingEdge(View childInSelectedRow,
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int topSelectionPixel, int bottomSelectionPixel) {
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Some of the newly selected item extends below the bottom of the
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // list
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (childInSelectedRow.getBottom() > bottomSelectionPixel) {
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Find space available above the selection into which we can
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // scroll upwards
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int spaceAbove = childInSelectedRow.getTop() - topSelectionPixel;
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Find space required to bring the bottom of the selected item
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // fully into view
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int spaceBelow = childInSelectedRow.getBottom() - bottomSelectionPixel;
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int offset = Math.min(spaceAbove, spaceBelow);
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Now offset the selected item to get it into view
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            offsetChildrenTopAndBottom(-offset);
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Move all views upwards so the selected row does not interesect the top
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fading edge (if necessary).
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childInSelectedRow A child in the row that contains the selection
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param topSelectionPixel The topmost pixel we can draw the selection into
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param bottomSelectionPixel The bottommost pixel we can draw the
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        selection into
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void adjustForTopFadingEdge(View childInSelectedRow,
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int topSelectionPixel, int bottomSelectionPixel) {
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Some of the newly selected item extends above the top of the list
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (childInSelectedRow.getTop() < topSelectionPixel) {
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Find space required to bring the top of the selected item
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // fully into view
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int spaceAbove = topSelectionPixel - childInSelectedRow.getTop();
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Find space available below the selection into which we can
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // scroll downwards
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int spaceBelow = bottomSelectionPixel - childInSelectedRow.getBottom();
8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int offset = Math.min(spaceAbove, spaceBelow);
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Now offset the selected item to get it into view
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            offsetChildrenTopAndBottom(offset);
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
812499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     * Smoothly scroll to the specified adapter position. The view will
813499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     * scroll such that the indicated position is displayed.
814499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     * @param position Scroll to this adapter position.
815499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     */
816499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    @android.view.RemotableViewMethod
817499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    public void smoothScrollToPosition(int position) {
818499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        super.smoothScrollToPosition(position);
819499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    }
820499cb9f516062b654952d282f211bee44c31a3c2Winson Chung
821499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    /**
822499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     * Smoothly scroll to the specified adapter position offset. The view will
823499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     * scroll such that the indicated position is displayed.
824499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     * @param offset The amount to offset from the adapter position to scroll to.
825499cb9f516062b654952d282f211bee44c31a3c2Winson Chung     */
826499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    @android.view.RemotableViewMethod
827499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    public void smoothScrollByOffset(int offset) {
828499cb9f516062b654952d282f211bee44c31a3c2Winson Chung        super.smoothScrollByOffset(offset);
829499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    }
830499cb9f516062b654952d282f211bee44c31a3c2Winson Chung
831499cb9f516062b654952d282f211bee44c31a3c2Winson Chung    /**
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Fills the grid based on positioning the new selection relative to the old
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * selection. The new selection will be placed at, above, or below the
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * location of the new selection depending on how the selection is moving.
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The selection will then be pinned to the visible part of the screen,
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * excluding the edges that are faded. The grid is then filled upwards and
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * downwards from there.
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param delta Which way we are moving
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childrenTop Where to start drawing children
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childrenBottom Last pixel where children can be drawn
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The view that currently has selection
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View moveSelection(int delta, int childrenTop, int childrenBottom) {
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int fadingEdgeLength = getVerticalFadingEdgeLength();
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int selectedPosition = mSelectedPosition;
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int numColumns = mNumColumns;
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int verticalSpacing = mVerticalSpacing;
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int oldRowStart;
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int rowStart;
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int rowEnd = -1;
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            oldRowStart = (selectedPosition - delta) - ((selectedPosition - delta) % numColumns);
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowStart = selectedPosition - (selectedPosition % numColumns);
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int invertedSelection = mItemCount - 1 - selectedPosition;
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns));
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowStart = Math.max(0, rowEnd - numColumns + 1);
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            invertedSelection = mItemCount - 1 - (selectedPosition - delta);
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            oldRowStart = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns));
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            oldRowStart = Math.max(0, oldRowStart - numColumns + 1);
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int rowDelta = rowStart - oldRowStart;
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength, rowStart);
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int bottomSelectionPixel = getBottomSelectionPixel(childrenBottom, fadingEdgeLength,
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                numColumns, rowStart);
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Possibly changed again in fillUp if we add rows above this one.
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mFirstPosition = rowStart;
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View sel;
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View referenceView;
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (rowDelta > 0) {
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Case 1: Scrolling down.
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int oldBottom = mReferenceViewInSelectedRow == null ? 0 :
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mReferenceViewInSelectedRow.getBottom();
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sel = makeRow(mStackFromBottom ? rowEnd : rowStart, oldBottom + verticalSpacing, true);
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            referenceView = mReferenceView;
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            adjustForBottomFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel);
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (rowDelta < 0) {
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Case 2: Scrolling up.
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int oldTop = mReferenceViewInSelectedRow == null ?
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    0 : mReferenceViewInSelectedRow .getTop();
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sel = makeRow(mStackFromBottom ? rowEnd : rowStart, oldTop - verticalSpacing, false);
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            referenceView = mReferenceView;
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            adjustForTopFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel);
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            /*
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             * Keep selection where it was
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             */
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int oldTop = mReferenceViewInSelectedRow == null ?
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    0 : mReferenceViewInSelectedRow .getTop();
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            sel = makeRow(mStackFromBottom ? rowEnd : rowStart, oldTop, true);
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            referenceView = mReferenceView;
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillUp(rowStart - numColumns, referenceView.getTop() - verticalSpacing);
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            adjustViewsUpOrDown();
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillDown(rowStart + numColumns, referenceView.getBottom() + verticalSpacing);
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillDown(rowEnd + numColumns, referenceView.getBottom() + verticalSpacing);
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            adjustViewsUpOrDown();
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fillUp(rowStart - 1, referenceView.getTop() - verticalSpacing);
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sel;
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
928edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski    private boolean determineColumns(int availableSpace) {
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int requestedHorizontalSpacing = mRequestedHorizontalSpacing;
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int stretchMode = mStretchMode;
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int requestedColumnWidth = mRequestedColumnWidth;
932edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski        boolean didNotInitiallyFit = false;
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mRequestedNumColumns == AUTO_FIT) {
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (requestedColumnWidth > 0) {
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Client told us to pick the number of columns
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mNumColumns = (availableSpace + requestedHorizontalSpacing) /
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        (requestedColumnWidth + requestedHorizontalSpacing);
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Just make up a number if we don't have enough info
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mNumColumns = 2;
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // We picked the columns
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNumColumns = mRequestedNumColumns;
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mNumColumns <= 0) {
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNumColumns = 1;
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (stretchMode) {
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        case NO_STRETCH:
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Nobody stretches
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mColumnWidth = requestedColumnWidth;
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHorizontalSpacing = requestedHorizontalSpacing;
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        default:
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int spaceLeftOver = availableSpace - (mNumColumns * requestedColumnWidth) -
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((mNumColumns - 1) * requestedHorizontalSpacing);
962edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski
963edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski            if (spaceLeftOver < 0) {
964edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski                didNotInitiallyFit = true;
965edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski            }
966edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski
9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (stretchMode) {
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case STRETCH_COLUMN_WIDTH:
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Stretch the columns
9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mColumnWidth = requestedColumnWidth + spaceLeftOver / mNumColumns;
9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mHorizontalSpacing = requestedHorizontalSpacing;
9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case STRETCH_SPACING:
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Stretch the spacing between columns
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mColumnWidth = requestedColumnWidth;
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mNumColumns > 1) {
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mHorizontalSpacing = requestedHorizontalSpacing +
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        spaceLeftOver / (mNumColumns - 1);
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mHorizontalSpacing = requestedHorizontalSpacing + spaceLeftOver;
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case STRETCH_SPACING_UNIFORM:
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Stretch the spacing between columns
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mColumnWidth = requestedColumnWidth;
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mNumColumns > 1) {
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mHorizontalSpacing = requestedHorizontalSpacing +
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        spaceLeftOver / (mNumColumns + 1);
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mHorizontalSpacing = requestedHorizontalSpacing + spaceLeftOver;
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
999edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski        return didNotInitiallyFit;
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Sets up mListPadding
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (widthMode == MeasureSpec.UNSPECIFIED) {
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mColumnWidth > 0) {
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                widthSize = mColumnWidth + mListPadding.left + mListPadding.right;
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                widthSize = mListPadding.left + mListPadding.right;
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            widthSize += getVerticalScrollbarWidth();
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childWidth = widthSize - mListPadding.left - mListPadding.right;
1022edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski        boolean didNotInitiallyFit = determineColumns(childWidth);
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childHeight = 0;
1025189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn        int childState = 0;
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int count = mItemCount;
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (count > 0) {
103021875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy            final View child = obtainView(0, mIsScrap);
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1032aebd28f729fa28016d70551d0372ab7fcd56ee1aAdam Powell            AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams();
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (p == null) {
1034aebd28f729fa28016d70551d0372ab7fcd56ee1aAdam Powell                p = (AbsListView.LayoutParams) generateDefaultLayoutParams();
10354df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                child.setLayoutParams(p);
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.viewType = mAdapter.getItemViewType(0);
10380bf88594c43ced48d862d122e3e84967b3b63658Romain Guy            p.forceAdd = true;
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int childHeightSpec = getChildMeasureSpec(
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int childWidthSpec = getChildMeasureSpec(
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            child.measure(childWidthSpec, childHeightSpec);
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            childHeight = child.getMeasuredHeight();
1047189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn            childState = combineMeasuredStates(childState, child.getMeasuredState());
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mRecycler.shouldRecycleViewType(p.viewType)) {
1050079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                mRecycler.addScrapView(child, -1);
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (heightMode == MeasureSpec.UNSPECIFIED) {
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            heightSize = mListPadding.top + mListPadding.bottom + childHeight +
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    getVerticalFadingEdgeLength() * 2;
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (heightMode == MeasureSpec.AT_MOST) {
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int ourSize =  mListPadding.top + mListPadding.bottom;
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int numColumns = mNumColumns;
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < count; i += numColumns) {
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ourSize += childHeight;
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (i + numColumns < count) {
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ourSize += mVerticalSpacing;
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (ourSize >= heightSize) {
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ourSize = heightSize;
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            heightSize = ourSize;
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1076189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn        if (widthMode == MeasureSpec.AT_MOST && mRequestedNumColumns != AUTO_FIT) {
1077189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn            int ourSize = (mRequestedNumColumns*mColumnWidth)
1078189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                    + ((mRequestedNumColumns-1)*mHorizontalSpacing)
1079189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                    + mListPadding.left + mListPadding.right;
1080edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski            if (ourSize > widthSize || didNotInitiallyFit) {
1081189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                widthSize |= MEASURED_STATE_TOO_SMALL;
1082189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn            }
1083189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn        }
1084189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setMeasuredDimension(widthSize, heightSize);
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWidthMeasureSpec = widthMeasureSpec;
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void attachLayoutAnimationParameters(View child,
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ViewGroup.LayoutParams params, int index, int count) {
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        GridLayoutAnimationController.AnimationParameters animationParams =
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                (GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters;
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (animationParams == null) {
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            animationParams = new GridLayoutAnimationController.AnimationParameters();
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            params.layoutAnimationParameters = animationParams;
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        animationParams.count = count;
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        animationParams.index = index;
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        animationParams.columnsCount = mNumColumns;
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        animationParams.rowsCount = count / mNumColumns;
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            animationParams.column = index % mNumColumns;
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            animationParams.row = index / mNumColumns;
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int invertedIndex = count - 1 - index;
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            animationParams.column = mNumColumns - 1 - (invertedIndex % mNumColumns);
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            animationParams.row = animationParams.rowsCount - 1 - invertedIndex / mNumColumns;
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void layoutChildren() {
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean blockLayoutRequests = mBlockLayoutRequests;
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!blockLayoutRequests) {
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBlockLayoutRequests = true;
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super.layoutChildren();
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            invalidate();
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mAdapter == null) {
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                resetList();
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                invokeOnItemScrollListener();
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int childrenTop = mListPadding.top;
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int childrenBottom = mBottom - mTop - mListPadding.bottom;
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int childCount = getChildCount();
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int index;
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int delta = 0;
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View sel;
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View oldSel = null;
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View oldFirst = null;
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View newSel = null;
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Remember stuff we will need down below
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (mLayoutMode) {
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_SET_SELECTION:
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                index = mNextSelectedPosition - mFirstPosition;
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (index >= 0 && index < childCount) {
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    newSel = getChildAt(index);
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_FORCE_TOP:
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_FORCE_BOTTOM:
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_SPECIFIC:
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_SYNC:
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_MOVE_SELECTION:
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mNextSelectedPosition >= 0) {
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    delta = mNextSelectedPosition - mSelectedPosition;
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Remember the previously selected view
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                index = mSelectedPosition - mFirstPosition;
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (index >= 0 && index < childCount) {
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    oldSel = getChildAt(index);
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Remember the previous first child
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                oldFirst = getChildAt(0);
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean dataChanged = mDataChanged;
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (dataChanged) {
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handleDataChanged();
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Handle the empty set by removing all views that are visible
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // and calling it a day
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mItemCount == 0) {
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                resetList();
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                invokeOnItemScrollListener();
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setSelectedPositionInt(mNextSelectedPosition);
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Pull all children into the RecycleBin.
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // These views will be reused if possible
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int firstPosition = mFirstPosition;
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final RecycleBin recycleBin = mRecycler;
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (dataChanged) {
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i = 0; i < childCount; i++) {
1198079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                    recycleBin.addScrapView(getChildAt(i), firstPosition+i);
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                recycleBin.fillActiveViews(childCount, firstPosition);
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Clear out old views
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //removeAllViewsInLayout();
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            detachAllViewsFromParent();
1207539ee8716b4f81260bab2e9f3dc5d88d81c99985Adam Powell            recycleBin.removeSkippedScrap();
12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (mLayoutMode) {
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_SET_SELECTION:
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (newSel != null) {
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    sel = fillFromSelection(newSel.getTop(), childrenTop, childrenBottom);
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    sel = fillSelection(childrenTop, childrenBottom);
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_FORCE_TOP:
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mFirstPosition = 0;
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sel = fillFromTop(childrenTop);
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                adjustViewsUpOrDown();
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_FORCE_BOTTOM:
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sel = fillUp(mItemCount - 1, childrenBottom);
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                adjustViewsUpOrDown();
12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_SPECIFIC:
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sel = fillSpecific(mSelectedPosition, mSpecificTop);
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_SYNC:
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sel = fillSpecific(mSyncPosition, mSpecificTop);
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case LAYOUT_MOVE_SELECTION:
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Move the selection relative to its old position
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                sel = moveSelection(delta, childrenTop, childrenBottom);
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (childCount == 0) {
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (!mStackFromBottom) {
123991c8613679959a5fde4f72fe6dd80023d9a1a9e7Romain Guy                        setSelectedPositionInt(mAdapter == null || isInTouchMode() ?
124091c8613679959a5fde4f72fe6dd80023d9a1a9e7Romain Guy                                INVALID_POSITION : 0);
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sel = fillFromTop(childrenTop);
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final int last = mItemCount - 1;
124491c8613679959a5fde4f72fe6dd80023d9a1a9e7Romain Guy                        setSelectedPositionInt(mAdapter == null || isInTouchMode() ?
124591c8613679959a5fde4f72fe6dd80023d9a1a9e7Romain Guy                                INVALID_POSITION : last);
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sel = fillFromBottom(last, childrenBottom);
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mSelectedPosition >= 0 && mSelectedPosition < mItemCount) {
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sel = fillSpecific(mSelectedPosition, oldSel == null ?
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                childrenTop : oldSel.getTop());
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else if (mFirstPosition < mItemCount)  {
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sel = fillSpecific(mFirstPosition, oldFirst == null ?
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                childrenTop : oldFirst.getTop());
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        sel = fillSpecific(0, childrenTop);
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Flush any cached views that did not get reused above
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            recycleBin.scrapActiveViews();
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (sel != null) {
1266079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn               positionSelector(INVALID_POSITION, sel);
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project               mSelectedTop = sel.getTop();
12683616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy            } else if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) {
12693616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy                View child = getChildAt(mMotionPosition - mFirstPosition);
1270079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                if (child != null) positionSelector(mMotionPosition, child);
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
12723616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy                mSelectedTop = 0;
12733616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy                mSelectorRect.setEmpty();
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLayoutMode = LAYOUT_NORMAL;
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDataChanged = false;
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mNeedSync = false;
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setNextSelectedPositionInt(mSelectedPosition);
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            updateScrollIndicators();
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mItemCount > 0) {
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                checkSelectionChanged();
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            invokeOnItemScrollListener();
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!blockLayoutRequests) {
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBlockLayoutRequests = false;
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Obtain the view and add it to our list of children. The view can be made
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * fresh, converted from an unused view, or used as is if it was in the
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * recycle bin.
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param position Logical position in the list
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y Top or bottom edge of the view to add
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flow if true, align top edge to y. If false, align bottom edge to
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        y.
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childrenLeft Left edge where children should be positioned
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selected Is this position selected?
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param where to add new item in the list
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return View that was added
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean selected, int where) {
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        View child;
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mDataChanged) {
131521875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy            // Try to use an existing view for this position
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            child = mRecycler.getActiveView(position);
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (child != null) {
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Found it -- we're using an existing child
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // This just needs to be positioned
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setupChild(child, position, y, flow, childrenLeft, selected, true, where);
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return child;
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Make a new view for this position, or convert an unused view if
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // possible
132721875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy        child = obtainView(position, mIsScrap);
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This needs to be positioned and measured
133021875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy        setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0], where);
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return child;
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Add a view as a child and make sure it is measured (if necessary) and
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * positioned properly.
13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param child The view to add
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param position The position of the view
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param y The y position relative to which this view will be positioned
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param flow if true, align top edge to y. If false, align bottom edge
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        to y.
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childrenLeft Left edge where children should be positioned
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param selected Is this position selected?
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param recycled Has this view been pulled from the recycle bin? If so it
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        does not need to be remeasured.
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param where Where to add the item in the list
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void setupChild(View child, int position, int y, boolean flow, int childrenLeft,
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean selected, boolean recycled, int where) {
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isSelected = selected && shouldShowSelector();
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final boolean updateChildSelected = isSelected != child.isSelected();
13553616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy        final int mode = mTouchMode;
13563616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy        final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL &&
13573616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy                mMotionPosition == position;
13583616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy        final boolean updateChildPressed = isPressed != child.isPressed();
13593616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested();
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Respect layout params that are already in the view. Otherwise make
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // some up...
1364aebd28f729fa28016d70551d0372ab7fcd56ee1aAdam Powell        AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams();
13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (p == null) {
1366aebd28f729fa28016d70551d0372ab7fcd56ee1aAdam Powell            p = (AbsListView.LayoutParams) generateDefaultLayoutParams();
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        p.viewType = mAdapter.getItemViewType(position);
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13700bf88594c43ced48d862d122e3e84967b3b63658Romain Guy        if (recycled && !p.forceAdd) {
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            attachViewToParent(child, where, p);
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
13730bf88594c43ced48d862d122e3e84967b3b63658Romain Guy            p.forceAdd = false;
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            addViewInLayout(child, where, p, true);
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (updateChildSelected) {
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            child.setSelected(isSelected);
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (isSelected) {
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                requestFocus();
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13843616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy        if (updateChildPressed) {
13853616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy            child.setPressed(isPressed);
13863616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy        }
13873616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy
1388f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell        if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) {
1389f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell            if (child instanceof Checkable) {
1390f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell                ((Checkable) child).setChecked(mCheckStates.get(position));
1391d0fa371f276fde32d81c037006941bc93da0bb03Dianne Hackborn            } else if (getContext().getApplicationInfo().targetSdkVersion
1392d0fa371f276fde32d81c037006941bc93da0bb03Dianne Hackborn                    >= android.os.Build.VERSION_CODES.HONEYCOMB) {
1393d0fa371f276fde32d81c037006941bc93da0bb03Dianne Hackborn                child.setActivated(mCheckStates.get(position));
1394f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell            }
1395f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell        }
1396f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (needToMeasure) {
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int childHeightSpec = ViewGroup.getChildMeasureSpec(
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height);
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int childWidthSpec = ViewGroup.getChildMeasureSpec(
14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            child.measure(childWidthSpec, childHeightSpec);
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cleanupLayoutState(child);
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int w = child.getMeasuredWidth();
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int h = child.getMeasuredHeight();
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int childLeft;
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int childTop = flow ? y : y - h;
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1414c0053223bedf33581b0830fb87be32c1f26e5372Fabrice Di Meglio        final int layoutDirection = getResolvedLayoutDirection();
1415c0053223bedf33581b0830fb87be32c1f26e5372Fabrice Di Meglio        final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
14166a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio        switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
14176a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio            case Gravity.LEFT:
14186a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio                childLeft = childrenLeft;
14196a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio                break;
14206a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio            case Gravity.CENTER_HORIZONTAL:
14216a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio                childLeft = childrenLeft + ((mColumnWidth - w) / 2);
14226a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio                break;
14236a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio            case Gravity.RIGHT:
14246a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio                childLeft = childrenLeft + mColumnWidth - w;
14256a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio                break;
14266a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio            default:
14276a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio                childLeft = childrenLeft;
14286a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio                break;
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (needToMeasure) {
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int childRight = childLeft + w;
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int childBottom = childTop + h;
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            child.layout(childLeft, childTop, childRight, childBottom);
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            child.offsetLeftAndRight(childLeft - child.getLeft());
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            child.offsetTopAndBottom(childTop - child.getTop());
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCachingStarted) {
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            child.setDrawingCacheEnabled(true);
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1443079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn
1444079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        if (recycled && (((AbsListView.LayoutParams)child.getLayoutParams()).scrappedFromPosition)
1445079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn                != position) {
1446079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn            child.jumpDrawablesToCurrentState();
1447079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn        }
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the currently selected item
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param position Index (starting at 0) of the data item to be selected.
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If in touch mode, the item will not be selected but it will still be positioned
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * appropriately.
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setSelection(int position) {
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!isInTouchMode()) {
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setNextSelectedPositionInt(position);
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mResurrectToPosition = position;
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLayoutMode = LAYOUT_SET_SELECTION;
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        requestLayout();
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Makes the item at the supplied position selected.
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param position the position of the new selection
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setSelectionInt(int position) {
1476f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron        int previousSelectedPosition = mNextSelectedPosition;
1477f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setNextSelectedPositionInt(position);
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        layoutChildren();
1480f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron
1481f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron        final int next = mStackFromBottom ? mItemCount - 1  - mNextSelectedPosition :
1482f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron            mNextSelectedPosition;
1483f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron        final int previous = mStackFromBottom ? mItemCount - 1
1484f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron                - previousSelectedPosition : previousSelectedPosition;
1485f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron
1486f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron        final int nextRow = next / mNumColumns;
1487f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron        final int previousRow = previous / mNumColumns;
1488f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron
1489f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron        if (nextRow != previousRow) {
1490f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron            awakenScrollBars();
1491f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron        }
1492f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron
14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKeyDown(int keyCode, KeyEvent event) {
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return commonKey(keyCode, 1, event);
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return commonKey(keyCode, repeatCount, event);
15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onKeyUp(int keyCode, KeyEvent event) {
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return commonKey(keyCode, 1, event);
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean commonKey(int keyCode, int count, KeyEvent event) {
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mAdapter == null) {
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDataChanged) {
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            layoutChildren();
15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean handled = false;
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int action = event.getAction();
15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (action != KeyEvent.ACTION_UP) {
15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (keyCode) {
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_LEFT:
15254e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    if (event.hasNoModifiers()) {
15268d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_LEFT);
15274e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    }
15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_RIGHT:
15314e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    if (event.hasNoModifiers()) {
15328d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_RIGHT);
15334e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    }
15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_UP:
15374e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    if (event.hasNoModifiers()) {
15388d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_UP);
15394e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
15408d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP);
15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
15439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_DOWN:
15454e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    if (event.hasNoModifiers()) {
15468d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_DOWN);
15474e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
15488d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN);
15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_DPAD_CENTER:
15538d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                case KeyEvent.KEYCODE_ENTER:
15548d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                    if (event.hasNoModifiers()) {
15558d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded();
15568d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        if (!handled
15578d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                                && event.getRepeatCount() == 0 && getChildCount() > 0) {
15588d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                            keyPressed();
15598d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                            handled = true;
15608d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        }
15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
15628d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                    break;
15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case KeyEvent.KEYCODE_SPACE:
15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mPopup == null || !mPopup.isShowing()) {
15664e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                        if (event.hasNoModifiers()) {
15678d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                            handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_DOWN);
15684e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                        } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
15698d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                            handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_UP);
15704e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                        }
15714e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    }
15724e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    break;
15734e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
15744e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                case KeyEvent.KEYCODE_PAGE_UP:
15754e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    if (event.hasNoModifiers()) {
15768d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_UP);
15774e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
15788d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP);
15794e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    }
15804e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    break;
15814e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
15824e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                case KeyEvent.KEYCODE_PAGE_DOWN:
15834e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    if (event.hasNoModifiers()) {
15848d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_DOWN);
15854e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) {
15868d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN);
15874e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    }
15884e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    break;
15894e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
15904e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                case KeyEvent.KEYCODE_MOVE_HOME:
15914e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    if (event.hasNoModifiers()) {
15928d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP);
15934e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    }
15944e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    break;
15954e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
15964e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                case KeyEvent.KEYCODE_MOVE_END:
15974e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    if (event.hasNoModifiers()) {
15988d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                        handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN);
15994e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    }
16004e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    break;
16014e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
16024e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                case KeyEvent.KEYCODE_TAB:
16034e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    // XXX Sometimes it is useful to be able to TAB through the items in
16044e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    //     a GridView sequentially.  Unfortunately this can create an
16054e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    //     asymmetry in TAB navigation order unless the list selection
16064e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    //     always reverts to the top or bottom when receiving TAB focus from
16074e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    //     another widget.  Leaving this behavior disabled for now but
16084e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    //     perhaps it should be configurable (and more comprehensive).
16094e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    if (false) {
16104e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                        if (event.hasNoModifiers()) {
16118d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                            handled = resurrectSelectionIfNeeded()
16128d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                                    || sequenceScroll(FOCUS_FORWARD);
16134e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                        } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
16148d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                            handled = resurrectSelectionIfNeeded()
16158d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                                    || sequenceScroll(FOCUS_BACKWARD);
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16228d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown        if (handled) {
16238d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown            return true;
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16268d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown        if (sendToTextFilter(keyCode, count, event)) {
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
16288d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown        }
16298d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown
16308d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown        switch (action) {
16318d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown            case KeyEvent.ACTION_DOWN:
16328d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                return super.onKeyDown(keyCode, event);
16338d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown            case KeyEvent.ACTION_UP:
16348d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                return super.onKeyUp(keyCode, event);
16358d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown            case KeyEvent.ACTION_MULTIPLE:
16368d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                return super.onKeyMultiple(keyCode, count, event);
16378d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown            default:
16388d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown                return false;
16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Scrolls up or down by the number of items currently present on screen.
16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN}
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return whether selection was moved
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean pageScroll(int direction) {
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int nextPage = -1;
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (direction == FOCUS_UP) {
165264d50a67f44f6f8627b6d5203f0e3b26dc4f71e5Romain Guy            nextPage = Math.max(0, mSelectedPosition - getChildCount());
16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (direction == FOCUS_DOWN) {
165464d50a67f44f6f8627b6d5203f0e3b26dc4f71e5Romain Guy            nextPage = Math.min(mItemCount - 1, mSelectedPosition + getChildCount());
16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (nextPage >= 0) {
16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setSelectionInt(nextPage);
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            invokeOnItemScrollListener();
1660f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron            awakenScrollBars();
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Go to the last or first item if possible.
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN}.
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Whether selection was moved.
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean fullScroll(int direction) {
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean moved = false;
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (direction == FOCUS_UP) {
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLayoutMode = LAYOUT_SET_SELECTION;
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setSelectionInt(0);
16799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            invokeOnItemScrollListener();
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            moved = true;
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (direction == FOCUS_DOWN) {
16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLayoutMode = LAYOUT_SET_SELECTION;
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setSelectionInt(mItemCount - 1);
16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            invokeOnItemScrollListener();
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            moved = true;
16869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1687f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron
1688f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron        if (moved) {
1689f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron            awakenScrollBars();
1690f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron        }
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return moved;
16939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
16959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
16969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Scrolls to the next or previous item, horizontally or vertically.
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
16989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param direction either {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT},
16999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *        {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN}
17009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return whether selection was moved
17029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean arrowScroll(int direction) {
17049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int selectedPosition = mSelectedPosition;
17059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int numColumns = mNumColumns;
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int startOfRowPos;
17089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int endOfRowPos;
17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean moved = false;
17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startOfRowPos = (selectedPosition / numColumns) * numColumns;
17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endOfRowPos = Math.min(startOfRowPos + numColumns - 1, mItemCount - 1);
17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int invertedSelection = mItemCount - 1 - selectedPosition;
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            endOfRowPos = mItemCount - 1 - (invertedSelection / numColumns) * numColumns;
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startOfRowPos = Math.max(0, endOfRowPos - numColumns + 1);
17199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (direction) {
17229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case FOCUS_UP:
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (startOfRowPos > 0) {
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mLayoutMode = LAYOUT_MOVE_SELECTION;
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setSelectionInt(Math.max(0, selectedPosition - numColumns));
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    moved = true;
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
17299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case FOCUS_DOWN:
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (endOfRowPos < mItemCount - 1) {
17319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mLayoutMode = LAYOUT_MOVE_SELECTION;
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setSelectionInt(Math.min(selectedPosition + numColumns, mItemCount - 1));
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    moved = true;
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case FOCUS_LEFT:
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (selectedPosition > startOfRowPos) {
17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mLayoutMode = LAYOUT_MOVE_SELECTION;
173951d154b82b5ed95edb0a869414ecbcd4faa6a62cRomain Guy                    setSelectionInt(Math.max(0, selectedPosition - 1));
17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    moved = true;
17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case FOCUS_RIGHT:
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (selectedPosition < endOfRowPos) {
17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mLayoutMode = LAYOUT_MOVE_SELECTION;
174651d154b82b5ed95edb0a869414ecbcd4faa6a62cRomain Guy                    setSelectionInt(Math.min(selectedPosition + 1, mItemCount - 1));
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    moved = true;
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                break;
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (moved) {
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            invokeOnItemScrollListener();
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1757f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron        if (moved) {
1758f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron            awakenScrollBars();
1759f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron        }
1760f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return moved;
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17644e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown    /**
17654e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown     * Goes to the next or previous item according to the order set by the
17664e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown     * adapter.
17674e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown     */
17684e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown    boolean sequenceScroll(int direction) {
17694e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        int selectedPosition = mSelectedPosition;
17704e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        int numColumns = mNumColumns;
17714e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        int count = mItemCount;
17724e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
17734e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        int startOfRow;
17744e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        int endOfRow;
17754e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        if (!mStackFromBottom) {
17764e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            startOfRow = (selectedPosition / numColumns) * numColumns;
17774e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            endOfRow = Math.min(startOfRow + numColumns - 1, count - 1);
17784e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        } else {
17794e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            int invertedSelection = count - 1 - selectedPosition;
17804e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            endOfRow = count - 1 - (invertedSelection / numColumns) * numColumns;
17814e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            startOfRow = Math.max(0, endOfRow - numColumns + 1);
17824e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        }
17834e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
17844e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        boolean moved = false;
17854e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        boolean showScroll = false;
17864e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        switch (direction) {
17874e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            case FOCUS_FORWARD:
17884e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                if (selectedPosition < count - 1) {
17894e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    // Move to the next item.
17904e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    mLayoutMode = LAYOUT_MOVE_SELECTION;
17914e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    setSelectionInt(selectedPosition + 1);
17924e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    moved = true;
17934e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    // Show the scrollbar only if changing rows.
17944e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    showScroll = selectedPosition == endOfRow;
17954e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                }
17964e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                break;
17974e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
17984e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            case FOCUS_BACKWARD:
17994e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                if (selectedPosition > 0) {
18004e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    // Move to the previous item.
18014e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    mLayoutMode = LAYOUT_MOVE_SELECTION;
18024e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    setSelectionInt(selectedPosition - 1);
18034e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    moved = true;
18044e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    // Show the scrollbar only if changing rows.
18054e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                    showScroll = selectedPosition == startOfRow;
18064e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                }
18074e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                break;
18084e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        }
18094e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
18104e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        if (moved) {
18114e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction));
18124e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            invokeOnItemScrollListener();
18134e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        }
18144e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
18154e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        if (showScroll) {
18164e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            awakenScrollBars();
18174e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        }
18184e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
18194e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown        return moved;
18204e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown    }
18214e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown
18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int closestChildIndex = -1;
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (gainFocus && previouslyFocusedRect != null) {
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            previouslyFocusedRect.offset(mScrollX, mScrollY);
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // figure out which item should be selected based on previously
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // focused rect
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Rect otherRect = mTempRect;
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int minDistance = Integer.MAX_VALUE;
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int childCount = getChildCount();
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < childCount; i++) {
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // only consider view's on appropriate edge of grid
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!isCandidateSelection(i, direction)) {
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    continue;
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final View other = getChildAt(i);
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                other.getDrawingRect(otherRect);
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                offsetDescendantRectToMyCoords(other, otherRect);
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int distance = getDistance(previouslyFocusedRect, otherRect, direction);
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (distance < minDistance) {
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    minDistance = distance;
18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    closestChildIndex = i;
18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (closestChildIndex >= 0) {
18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setSelection(closestChildIndex + mFirstPosition);
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            requestLayout();
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Is childIndex a candidate for next focus given the direction the focus
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * change is coming from?
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param childIndex The index to check.
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param direction The direction, one of
18654e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown     *        {FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, FOCUS_BACKWARD}
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Whether childIndex is a candidate.
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isCandidateSelection(int childIndex, int direction) {
18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int count = getChildCount();
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int invertedIndex = count - 1 - childIndex;
18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int rowStart;
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int rowEnd;
18749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mStackFromBottom) {
18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowStart = childIndex - (childIndex % mNumColumns);
18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowEnd = Math.max(rowStart + mNumColumns - 1, count);
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowEnd = count - 1 - (invertedIndex - (invertedIndex % mNumColumns));
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            rowStart = Math.max(0, rowEnd - mNumColumns + 1);
18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (direction) {
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case View.FOCUS_RIGHT:
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // coming from left, selection is only valid if it is on left
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // edge
18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return childIndex == rowStart;
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case View.FOCUS_DOWN:
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // coming from top; only valid if in top row
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return rowStart == 0;
18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case View.FOCUS_LEFT:
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // coming from right, must be on right edge
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return childIndex == rowEnd;
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case View.FOCUS_UP:
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // coming from bottom, need to be in last row
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return rowEnd == count - 1;
18974e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            case View.FOCUS_FORWARD:
18984e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                // coming from top-left, need to be first in top row
18994e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                return childIndex == rowStart && rowStart == 0;
19004e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown            case View.FOCUS_BACKWARD:
19014e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                // coming from bottom-right, need to be last in bottom row
19024e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                return childIndex == rowEnd && rowEnd == count - 1;
19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            default:
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new IllegalArgumentException("direction must be one of "
19054e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                        + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, "
19064e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown                        + "FOCUS_FORWARD, FOCUS_BACKWARD}.");
19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Describes how the child views are horizontally aligned. Defaults to Gravity.LEFT
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param gravity the gravity to apply to this grid's children
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#GridView_gravity
19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setGravity(int gravity) {
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mGravity != gravity) {
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mGravity = gravity;
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            requestLayoutIfNecessary();
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the amount of horizontal (x) spacing to place between each item
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in the grid.
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param horizontalSpacing The amount of horizontal space between items,
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in pixels.
19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#GridView_horizontalSpacing
19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setHorizontalSpacing(int horizontalSpacing) {
19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (horizontalSpacing != mRequestedHorizontalSpacing) {
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRequestedHorizontalSpacing = horizontalSpacing;
19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            requestLayoutIfNecessary();
19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the amount of vertical (y) spacing to place between each item
19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in the grid.
19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param verticalSpacing The amount of vertical space between items,
19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * in pixels.
19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#GridView_verticalSpacing
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setVerticalSpacing(int verticalSpacing) {
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (verticalSpacing != mVerticalSpacing) {
19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mVerticalSpacing = verticalSpacing;
19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            requestLayoutIfNecessary();
19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Control how items are stretched to fill their space.
19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param stretchMode Either {@link #NO_STRETCH},
19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #STRETCH_SPACING}, {@link #STRETCH_SPACING_UNIFORM}, or {@link #STRETCH_COLUMN_WIDTH}.
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#GridView_stretchMode
19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setStretchMode(int stretchMode) {
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (stretchMode != mStretchMode) {
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStretchMode = stretchMode;
19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            requestLayoutIfNecessary();
19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStretchMode() {
19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStretchMode;
19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the width of columns in the grid.
19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param columnWidth The column width, in pixels.
19809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#GridView_columnWidth
19829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setColumnWidth(int columnWidth) {
19849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (columnWidth != mRequestedColumnWidth) {
19859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRequestedColumnWidth = columnWidth;
19869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            requestLayoutIfNecessary();
19879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
19899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set the number of columns in the grid
19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param numColumns The desired number of columns.
19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @attr ref android.R.styleable#GridView_numColumns
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setNumColumns(int numColumns) {
19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (numColumns != mRequestedNumColumns) {
19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mRequestedNumColumns = numColumns;
20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            requestLayoutIfNecessary();
20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20038d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein
20048d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein    /**
20058d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein     * Get the number of columns in the grid.
20068d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein     * Returns {@link #AUTO_FIT} if the Grid has never been laid out.
20078d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein     *
20088d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein     * @attr ref android.R.styleable#GridView_numColumns
20098d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein     *
20108d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein     * @see #setNumColumns(int)
20118d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein     */
20128d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein    @ViewDebug.ExportedProperty
20138d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein    public int getNumColumns() {
20148d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein        return mNumColumns;
20158d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein    }
20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Make sure views are touching the top or bottom edge, as appropriate for
20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * our gravity
20209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void adjustViewsUpOrDown() {
20229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int childCount = getChildCount();
20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (childCount > 0) {
20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int delta;
20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View child;
20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mStackFromBottom) {
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Uh-oh -- we came up short. Slide all views up to make them
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // align with the top
20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                child = getChildAt(0);
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delta = child.getTop() - mListPadding.top;
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFirstPosition != 0) {
20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // It's OK to have some space above the first item if it is
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // part of the vertical spacing
20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    delta -= mVerticalSpacing;
20379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (delta < 0) {
20399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We only are looking to see if we are too low, not too high
20409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    delta = 0;
20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
20439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // we are too high, slide all views down to align with bottom
20449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                child = getChildAt(childCount - 1);
20459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                delta = child.getBottom() - (getHeight() - mListPadding.bottom);
20469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mFirstPosition + childCount < mItemCount) {
20489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // It's OK to have some space below the last item if it is
20499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // part of the vertical spacing
20509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    delta += mVerticalSpacing;
20519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (delta > 0) {
20549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We only are looking to see if we are too high, not too low
20559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    delta = 0;
20569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (delta != 0) {
20609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                offsetChildrenTopAndBottom(-delta);
20619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
20669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected int computeVerticalScrollExtent() {
20679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int count = getChildCount();
20689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (count > 0) {
20699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int numColumns = mNumColumns;
20709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int rowCount = (count + numColumns - 1) / numColumns;
20719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int extent = rowCount * 100;
20739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            View view = getChildAt(0);
20759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int top = view.getTop();
20769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int height = view.getHeight();
20779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (height > 0) {
20789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                extent += (top * 100) / height;
20799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            view = getChildAt(count - 1);
20829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int bottom = view.getBottom();
20839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            height = view.getHeight();
20849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (height > 0) {
20859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                extent -= ((bottom - getHeight()) * 100) / height;
20869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return extent;
20899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
20919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
20929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
20939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
20949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected int computeVerticalScrollOffset() {
20959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFirstPosition >= 0 && getChildCount() > 0) {
20969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final View view = getChildAt(0);
20979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final int top = view.getTop();
20989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int height = view.getHeight();
20999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (height > 0) {
2100f2a204e792df5593cfe54efc95d04b7e764795c1Adam Powell                final int numColumns = mNumColumns;
2101f2a204e792df5593cfe54efc95d04b7e764795c1Adam Powell                final int whichRow = mFirstPosition / numColumns;
2102f2a204e792df5593cfe54efc95d04b7e764795c1Adam Powell                final int rowCount = (mItemCount + numColumns - 1) / numColumns;
2103f2a204e792df5593cfe54efc95d04b7e764795c1Adam Powell                return Math.max(whichRow * 100 - (top * 100) / height +
2104f2a204e792df5593cfe54efc95d04b7e764795c1Adam Powell                        (int) ((float) mScrollY / getHeight() * rowCount * 100), 0);
21059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return 0;
21089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
21119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected int computeVerticalScrollRange() {
21129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // TODO: Account for vertical spacing too
21139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int numColumns = mNumColumns;
21149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int rowCount = (mItemCount + numColumns - 1) / numColumns;
2115637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell        int result = Math.max(rowCount * 100, 0);
2116637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell        if (mScrollY != 0) {
2117637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell            // Compensate for overscroll
2118637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell            result += Math.abs((int) ((float) mScrollY / getHeight() * rowCount * 100));
2119637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell        }
2120637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell        return result;
21219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
21229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21238a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
21248a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
21258a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityEvent(event);
21268a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        event.setClassName(GridView.class.getName());
21278a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
21288a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
21298a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
21308a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
21318a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityNodeInfo(info);
21328a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        info.setClassName(GridView.class.getName());
21338a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
21348a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov}
2135