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 19d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbyeimport android.annotation.IntDef; 2094a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamyimport android.annotation.NonNull; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 22499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.content.Intent; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 2523f4432437b2ab742971055b7eb79b346894f24bAlan Viveretteimport android.os.Bundle; 265fade8c69aef621312232ef0647502d7a63990b9Romain Guyimport android.os.Trace; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 285d565faab21324862fa24490f116424e1b668b1dAlan Viveretteimport android.util.MathUtils; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Gravity; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 31499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.view.SoundEffectConstants; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 338d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sappersteinimport android.view.ViewDebug; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup; 3594a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamyimport android.view.ViewHierarchyEncoder; 363e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viveretteimport android.view.ViewRootImpl; 378a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 3823f4432437b2ab742971055b7eb79b346894f24bAlan Viveretteimport android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; 395b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viveretteimport android.view.accessibility.AccessibilityNodeInfo.CollectionInfo; 405b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viveretteimport android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo; 4199441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikasimport android.view.accessibility.AccessibilityNodeProvider; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.animation.GridLayoutAnimationController; 43499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.widget.RemoteViews.RemoteView; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4523f4432437b2ab742971055b7eb79b346894f24bAlan Viveretteimport com.android.internal.R; 4623f4432437b2ab742971055b7eb79b346894f24bAlan Viverette 47d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbyeimport java.lang.annotation.Retention; 48d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbyeimport java.lang.annotation.RetentionPolicy; 49d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A view that shows items in two-dimensional scrolling grid. The items in the 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * grid come from the {@link ListAdapter} associated with this view. 5441ec65355bd6ded652769725b276d47c54a0d913Scott Main * 554c359b76f9a030f92a302ba74a528faa170bad4eScott Main * <p>See the <a href="{@docRoot}guide/topics/ui/layout/gridview.html">Grid 564c359b76f9a030f92a302ba74a528faa170bad4eScott Main * View</a> guide.</p> 5799441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * 5884c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_horizontalSpacing 5984c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_verticalSpacing 6084c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_stretchMode 6184c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_columnWidth 6284c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_numColumns 6384c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * @attr ref android.R.styleable#GridView_gravity 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 65499cb9f516062b654952d282f211bee44c31a3c2Winson Chung@RemoteView 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class GridView extends AbsListView { 67d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye /** @hide */ 68d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye @IntDef({NO_STRETCH, STRETCH_SPACING, STRETCH_COLUMN_WIDTH, STRETCH_SPACING_UNIFORM}) 69d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye @Retention(RetentionPolicy.SOURCE) 70d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye public @interface StretchMode {} 71d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye 7284c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy /** 7384c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * Disables stretching. 7499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * 7599441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * @see #setStretchMode(int) 7684c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy */ 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int NO_STRETCH = 0; 7884c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy /** 7984c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * Stretches the spacing between columns. 8099441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * 8199441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * @see #setStretchMode(int) 8284c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy */ 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int STRETCH_SPACING = 1; 8484c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy /** 8584c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * Stretches columns. 8699441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * 8799441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * @see #setStretchMode(int) 8884c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy */ 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int STRETCH_COLUMN_WIDTH = 2; 9084c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy /** 9184c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * Stretches the spacing between columns. The spacing is uniform. 9299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * 9399441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * @see #setStretchMode(int) 9484c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy */ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int STRETCH_SPACING_UNIFORM = 3; 9684c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy 9784c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy /** 9884c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy * Creates as many columns as can fit on screen. 9999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * 10099441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * @see #setNumColumns(int) 10184c6b95a7776ea5924a7c3e5a511c4df5c75924dRomain Guy */ 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int AUTO_FIT = -1; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mNumColumns = AUTO_FIT; 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mHorizontalSpacing = 0; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRequestedHorizontalSpacing; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mVerticalSpacing = 0; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mStretchMode = STRETCH_COLUMN_WIDTH; 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mColumnWidth; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRequestedColumnWidth; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRequestedNumColumns; 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View mReferenceView = null; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View mReferenceViewInSelectedRow = null; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 117a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio private int mGravity = Gravity.START; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Rect mTempRect = new Rect(); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GridView(Context context) { 12248774533f1cfe3036919a2f73631e07b7c284617Adam Powell this(context, null); 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public GridView(Context context, AttributeSet attrs) { 12623f4432437b2ab742971055b7eb79b346894f24bAlan Viverette this(context, attrs, R.attr.gridViewStyle); 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 129617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public GridView(Context context, AttributeSet attrs, int defStyleAttr) { 130617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette this(context, attrs, defStyleAttr, 0); 131617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette } 132617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 133617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public GridView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 134617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 136617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette final TypedArray a = context.obtainStyledAttributes( 13723f4432437b2ab742971055b7eb79b346894f24bAlan Viverette attrs, R.styleable.GridView, defStyleAttr, defStyleRes); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int hSpacing = a.getDimensionPixelOffset( 14023f4432437b2ab742971055b7eb79b346894f24bAlan Viverette R.styleable.GridView_horizontalSpacing, 0); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setHorizontalSpacing(hSpacing); 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int vSpacing = a.getDimensionPixelOffset( 14423f4432437b2ab742971055b7eb79b346894f24bAlan Viverette R.styleable.GridView_verticalSpacing, 0); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setVerticalSpacing(vSpacing); 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14723f4432437b2ab742971055b7eb79b346894f24bAlan Viverette int index = a.getInt(R.styleable.GridView_stretchMode, STRETCH_COLUMN_WIDTH); 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index >= 0) { 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setStretchMode(index); 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15223f4432437b2ab742971055b7eb79b346894f24bAlan Viverette int columnWidth = a.getDimensionPixelOffset(R.styleable.GridView_columnWidth, -1); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (columnWidth > 0) { 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setColumnWidth(columnWidth); 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15723f4432437b2ab742971055b7eb79b346894f24bAlan Viverette int numColumns = a.getInt(R.styleable.GridView_numColumns, 1); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setNumColumns(numColumns); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16023f4432437b2ab742971055b7eb79b346894f24bAlan Viverette index = a.getInt(R.styleable.GridView_gravity, -1); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index >= 0) { 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setGravity(index); 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ListAdapter getAdapter() { 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter; 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 174499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * Sets up this AbsListView to use a remote views adapter which connects to a RemoteViewsService 175499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * through the specified intent. 176499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * @param intent the intent used to identify the RemoteViewsService for the adapter to connect to. 177499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 1785c022639d7e1eebbeb190975980621a286bb2ff1Sunny Goyal @android.view.RemotableViewMethod(asyncImpl="setRemoteViewsAdapterAsync") 179499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public void setRemoteViewsAdapter(Intent intent) { 180499cb9f516062b654952d282f211bee44c31a3c2Winson Chung super.setRemoteViewsAdapter(intent); 181499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 182499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 183499cb9f516062b654952d282f211bee44c31a3c2Winson Chung /** 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the data behind this GridView. 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param adapter the adapter providing the grid's data 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAdapter(ListAdapter adapter) { 190df36b0579e1e550de3d66a20362717e49b23235cRomain Guy if (mAdapter != null && mDataSetObserver != null) { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAdapter.unregisterDataSetObserver(mDataSetObserver); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetList(); 19599441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas mRecycler.clear(); 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAdapter = adapter; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOldSelectedPosition = INVALID_POSITION; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOldSelectedRowId = INVALID_ROW_ID; 200f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell 201f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell // AbsListView#setAdapter will update choice mode states. 202f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell super.setAdapter(adapter); 203f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAdapter != null) { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOldItemCount = mItemCount; 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mItemCount = mAdapter.getCount(); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataChanged = true; 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkFocus(); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataSetObserver = new AdapterDataSetObserver(); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAdapter.registerDataSetObserver(mDataSetObserver); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRecycler.setViewTypeCount(mAdapter.getViewTypeCount()); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int position; 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStackFromBottom) { 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position = lookForSelectablePosition(mItemCount - 1, false); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position = lookForSelectablePosition(0, true); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectedPositionInt(position); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setNextSelectedPositionInt(position); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkSelectionChanged(); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 22599441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas checkFocus(); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Nothing selected 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkSelectionChanged(); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(); 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lookForSelectablePosition(int position, boolean lookDown) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ListAdapter adapter = mAdapter; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter == null || isInTouchMode()) { 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_POSITION; 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (position < 0 || position >= mItemCount) { 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_POSITION; 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return position; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@inheritDoc} 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void fillGap(boolean down) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numColumns = mNumColumns; 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int verticalSpacing = mVerticalSpacing; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = getChildCount(); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (down) { 2578c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell int paddingTop = 0; 2588c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) { 2598c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell paddingTop = getListPaddingTop(); 2608c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell } 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int startOffset = count > 0 ? 2628c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell getChildAt(count - 1).getBottom() + verticalSpacing : paddingTop; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int position = mFirstPosition + count; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStackFromBottom) { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position += numColumns - 1; 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(position, startOffset); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooHigh(numColumns, verticalSpacing, getChildCount()); 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2708c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell int paddingBottom = 0; 2718c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) { 2728c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell paddingBottom = getListPaddingBottom(); 2738c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell } 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int startOffset = count > 0 ? 2758c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell getChildAt(0).getTop() - verticalSpacing : getHeight() - paddingBottom; 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int position = mFirstPosition; 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position -= numColumns; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position--; 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(position, startOffset); 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooLow(numColumns, verticalSpacing, getChildCount()); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fills the list from pos down to the end of the list view. 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param pos The first position to put in the list 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nextTop The location where the top of the item associated with pos 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * should be drawn 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that is currently selected, if it happens to be in the 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * range that we draw. 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillDown(int pos, int nextTop) { 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View selectedView = null; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3018c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell int end = (mBottom - mTop); 3028c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) { 3038c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell end -= mListPadding.bottom; 3048c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (nextTop < end && pos < mItemCount) { 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View temp = makeRow(pos, nextTop, true); 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (temp != null) { 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedView = temp; 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3128bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy // mReferenceView will change with each call to makeRow() 3138bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy // do not cache in a local variable outside of this loop 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextTop = mReferenceView.getBottom() + mVerticalSpacing; 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos += mNumColumns; 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319b967392e0170af8cfd8053fd43fcdf8c46f703e9Adam Cohen setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return selectedView; 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View makeRow(int startPos, int y, boolean flow) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int columnWidth = mColumnWidth; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int horizontalSpacing = mHorizontalSpacing; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 327a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio final boolean isLayoutRtl = isLayoutRtl(); 328a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int last; 330a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio int nextLeft; 331a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio 332a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio if (isLayoutRtl) { 333a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio nextLeft = getWidth() - mListPadding.right - columnWidth - 334a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0); 335a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio } else { 336a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio nextLeft = mListPadding.left + 337a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio ((mStretchMode == STRETCH_SPACING_UNIFORM) ? horizontalSpacing : 0); 338a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio } 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project last = Math.min(startPos + mNumColumns, mItemCount); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project last = startPos + 1; 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startPos = Math.max(0, startPos - mNumColumns + 1); 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (last - startPos < mNumColumns) { 347a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio final int deltaLeft = (mNumColumns - (last - startPos)) * (columnWidth + horizontalSpacing); 348a598720ad6ae21a07aaae50c9469dc3799c3fc30Fabrice Di Meglio nextLeft += (isLayoutRtl ? -1 : +1) * deltaLeft; 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View selectedView = null; 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean hasFocus = shouldShowSelector(); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean inClick = touchModeDrawsInPressedState(); 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int selectedPosition = mSelectedPosition; 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3588bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy View child = null; 359661041194c0c5b0fe1ee659589531397e2d58d41Yigit Boyar final int nextChildDir = isLayoutRtl ? -1 : +1; 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int pos = startPos; pos < last; pos++) { 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // is this the selected item? 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean selected = pos == selectedPosition; 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // does the list view have focus or contain focus 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int where = flow ? -1 : pos - startPos; 3668bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy child = makeAndAddView(pos, y, flow, nextLeft, selected, where); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 368661041194c0c5b0fe1ee659589531397e2d58d41Yigit Boyar nextLeft += nextChildDir * columnWidth; 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pos < last - 1) { 370661041194c0c5b0fe1ee659589531397e2d58d41Yigit Boyar nextLeft += nextChildDir * horizontalSpacing; 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selected && (hasFocus || inClick)) { 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedView = child; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3788bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy mReferenceView = child; 37999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selectedView != null) { 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReferenceViewInSelectedRow = mReferenceView; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return selectedView; 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fills the list from pos up to the top of the list view. 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param pos The first position to put in the list 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nextBottom The location where the bottom of the item associated 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with pos should be drawn 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that is currently selected 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillUp(int pos, int nextBottom) { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View selectedView = null; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4008c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell int end = 0; 4018c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) { 4028c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell end = mListPadding.top; 4038c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell } 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (nextBottom > end && pos >= 0) { 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View temp = makeRow(pos, nextBottom, false); 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (temp != null) { 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedView = temp; 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextBottom = mReferenceView.getTop() - mVerticalSpacing; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = pos; 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos -= mNumColumns; 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStackFromBottom) { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = Math.max(0, pos + 1); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 423b967392e0170af8cfd8053fd43fcdf8c46f703e9Adam Cohen setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1); 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return selectedView; 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fills the list from top to bottom, starting with mFirstPosition 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nextTop The location where the top of the first item should be 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * drawn 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that is currently selected 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillFromTop(int nextTop) { 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = Math.min(mFirstPosition, mSelectedPosition); 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = Math.min(mFirstPosition, mItemCount - 1); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition < 0) { 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = 0; 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition -= mFirstPosition % mNumColumns; 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fillDown(mFirstPosition, nextTop); 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillFromBottom(int lastPosition, int nextBottom) { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lastPosition = Math.max(lastPosition, mSelectedPosition); 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lastPosition = Math.min(lastPosition, mItemCount - 1); 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int invertedPosition = mItemCount - 1 - lastPosition; 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lastPosition = mItemCount - 1 - (invertedPosition - (invertedPosition % mNumColumns)); 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fillUp(lastPosition, nextBottom); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillSelection(int childrenTop, int childrenBottom) { 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int selectedPosition = reconcileSelectedPosition(); 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numColumns = mNumColumns; 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int verticalSpacing = mVerticalSpacing; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rowStart; 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rowEnd = -1; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowStart = selectedPosition - (selectedPosition % numColumns); 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int invertedSelection = mItemCount - 1 - selectedPosition; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns)); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowStart = Math.max(0, rowEnd - numColumns + 1); 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int fadingEdgeLength = getVerticalFadingEdgeLength(); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength, rowStart); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View sel = makeRow(mStackFromBottom ? rowEnd : rowStart, topSelectionPixel, true); 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = rowStart; 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View referenceView = mReferenceView; 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(rowStart + numColumns, referenceView.getBottom() + verticalSpacing); 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pinToBottom(childrenBottom); 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(rowStart - numColumns, referenceView.getTop() - verticalSpacing); 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int bottomSelectionPixel = getBottomSelectionPixel(childrenBottom, 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fadingEdgeLength, numColumns, rowStart); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int offset = bottomSelectionPixel - referenceView.getBottom(); 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(offset); 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(rowStart - 1, referenceView.getTop() - verticalSpacing); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pinToTop(childrenTop); 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(rowEnd + numColumns, referenceView.getBottom() + verticalSpacing); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sel; 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void pinToTop(int childrenTop) { 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition == 0) { 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int top = getChildAt(0).getTop(); 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int offset = childrenTop - top; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset < 0) { 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(offset); 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void pinToBottom(int childrenBottom) { 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = getChildCount(); 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition + count == mItemCount) { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int bottom = getChildAt(count - 1).getBottom(); 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int offset = childrenBottom - bottom; 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (offset > 0) { 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(offset); 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 51899441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas } 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int findMotionRow(int y) { 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childCount = getChildCount(); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childCount > 0) { 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numColumns = mNumColumns; 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < childCount; i += numColumns) { 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (y <= getChildAt(i).getBottom()) { 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mFirstPosition + i; 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = childCount - 1; i >= 0; i -= numColumns) { 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (y >= getChildAt(i).getTop()) { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mFirstPosition + i; 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_POSITION; 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Layout during a scroll that results from tracking motion events. Places 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the mMotionPosition view at the offset specified by mMotionViewTop, and 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * then build surrounding views from there. 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position the position at which to start filling 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param top the top of the view at that position 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The selected view, or null if the selected view is outside the 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * visible area. 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillSpecific(int position, int top) { 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numColumns = mNumColumns; 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int motionRowStart; 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int motionRowEnd = -1; 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project motionRowStart = position - (position % numColumns); 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int invertedSelection = mItemCount - 1 - position; 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project motionRowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns)); 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project motionRowStart = Math.max(0, motionRowEnd - numColumns + 1); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View temp = makeRow(mStackFromBottom ? motionRowEnd : motionRowStart, top, true); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Possibly changed again in fillUp if we add rows above this one. 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = motionRowStart; 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View referenceView = mReferenceView; 5748bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy // We didn't have anything to layout, bail out 5758bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy if (referenceView == null) { 5768bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy return null; 5778bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy } 5788bcdc0764f2f569173863655f96cdec2aea2d0daRomain Guy 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int verticalSpacing = mVerticalSpacing; 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View above; 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View below; 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project above = fillUp(motionRowStart - numColumns, referenceView.getTop() - verticalSpacing); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project below = fillDown(motionRowStart + numColumns, referenceView.getBottom() + verticalSpacing); 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check if we have dragged the bottom of the grid too high 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childCount = getChildCount(); 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childCount > 0) { 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooHigh(numColumns, verticalSpacing, childCount); 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project below = fillDown(motionRowEnd + numColumns, referenceView.getBottom() + verticalSpacing); 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project above = fillUp(motionRowStart - 1, referenceView.getTop() - verticalSpacing); 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Check if we have dragged the bottom of the grid too high 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childCount = getChildCount(); 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childCount > 0) { 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooLow(numColumns, verticalSpacing, childCount); 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (temp != null) { 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return temp; 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (above != null) { 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return above; 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return below; 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void correctTooHigh(int numColumns, int verticalSpacing, int childCount) { 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // First see if the last item is visible 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int lastPosition = mFirstPosition + childCount - 1; 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lastPosition == mItemCount - 1 && childCount > 0) { 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the last child ... 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View lastChild = getChildAt(childCount - 1); 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ... and its bottom edge 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int lastBottom = lastChild.getBottom(); 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is bottom of our drawable area 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int end = (mBottom - mTop) - mListPadding.bottom; 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is how far the bottom edge of the last view is from the bottom of the 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // drawable area 62799441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas int bottomOffset = end - lastBottom; 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View firstChild = getChildAt(0); 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int firstTop = firstChild.getTop(); 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make sure we are 1) Too high, and 2) Either there are more rows above the 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // first row or the first row is scrolled off the top of the drawable area 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bottomOffset > 0 && (mFirstPosition > 0 || firstTop < mListPadding.top)) { 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition == 0) { 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't pull the top too far down 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottomOffset = Math.min(bottomOffset, mListPadding.top - firstTop); 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 63999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Move everything down 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(bottomOffset); 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition > 0) { 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fill the gap that was opened above mFirstPosition with more rows, if 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // possible 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(mFirstPosition - (mStackFromBottom ? 1 : numColumns), 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project firstChild.getTop() - verticalSpacing); 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Close up the remaining gap 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void correctTooLow(int numColumns, int verticalSpacing, int childCount) { 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition == 0 && childCount > 0) { 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the first child ... 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View firstChild = getChildAt(0); 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ... and its top edge 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int firstTop = firstChild.getTop(); 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is top of our drawable area 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int start = mListPadding.top; 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is bottom of our drawable area 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int end = (mBottom - mTop) - mListPadding.bottom; 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is how far the top edge of the first view is from the top of the 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // drawable area 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int topOffset = firstTop - start; 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View lastChild = getChildAt(childCount - 1); 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int lastBottom = lastChild.getBottom(); 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int lastPosition = mFirstPosition + childCount - 1; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make sure we are 1) Too low, and 2) Either there are more rows below the 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // last row or the last row is scrolled off the bottom of the drawable area 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (topOffset > 0 && (lastPosition < mItemCount - 1 || lastBottom > end)) { 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lastPosition == mItemCount - 1 ) { 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't pull the bottom too far up 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project topOffset = Math.min(topOffset, lastBottom - end); 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 68299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Move everything up 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(-topOffset); 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lastPosition < mItemCount - 1) { 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fill the gap that was opened below the last position with more rows, if 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // possible 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(lastPosition + (!mStackFromBottom ? 1 : numColumns), 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lastChild.getBottom() + verticalSpacing); 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Close up the remaining gap 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fills the grid based on positioning the new selection at a specific 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * location. The selection may be moved so that it does not intersect the 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * faded edges. The grid is then filled upwards and downwards from there. 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectedTop Where the selected item should be 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenTop Where to start drawing children 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenBottom Last pixel where children can be drawn 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that currently has selection 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillFromSelection(int selectedTop, int childrenTop, int childrenBottom) { 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int fadingEdgeLength = getVerticalFadingEdgeLength(); 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int selectedPosition = mSelectedPosition; 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numColumns = mNumColumns; 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int verticalSpacing = mVerticalSpacing; 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rowStart; 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rowEnd = -1; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowStart = selectedPosition - (selectedPosition % numColumns); 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int invertedSelection = mItemCount - 1 - selectedPosition; 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns)); 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowStart = Math.max(0, rowEnd - numColumns + 1); 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View sel; 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View referenceView; 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength, rowStart); 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int bottomSelectionPixel = getBottomSelectionPixel(childrenBottom, fadingEdgeLength, 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numColumns, rowStart); 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = makeRow(mStackFromBottom ? rowEnd : rowStart, selectedTop, true); 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Possibly changed again in fillUp if we add rows above this one. 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = rowStart; 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project referenceView = mReferenceView; 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustForTopFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustForBottomFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel); 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(rowStart - numColumns, referenceView.getTop() - verticalSpacing); 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(rowStart + numColumns, referenceView.getBottom() + verticalSpacing); 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(rowEnd + numColumns, referenceView.getBottom() + verticalSpacing); 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(rowStart - 1, referenceView.getTop() - verticalSpacing); 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sel; 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Calculate the bottom-most pixel we can draw the selection into 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenBottom Bottom pixel were children can be drawn 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param fadingEdgeLength Length of the fading edge in pixels, if present 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param numColumns Number of columns in the grid 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param rowStart The start of the row that will contain the selection 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The bottom-most pixel we can draw the selection into 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getBottomSelectionPixel(int childrenBottom, int fadingEdgeLength, 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numColumns, int rowStart) { 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Last pixel we can draw the selection into 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int bottomSelectionPixel = childrenBottom; 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rowStart + numColumns - 1 < mItemCount - 1) { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottomSelectionPixel -= fadingEdgeLength; 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return bottomSelectionPixel; 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Calculate the top-most pixel we can draw the selection into 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenTop Top pixel were children can be drawn 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param fadingEdgeLength Length of the fading edge in pixels, if present 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param rowStart The start of the row that will contain the selection 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The top-most pixel we can draw the selection into 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getTopSelectionPixel(int childrenTop, int fadingEdgeLength, int rowStart) { 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // first pixel we can draw the selection into 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int topSelectionPixel = childrenTop; 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rowStart > 0) { 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project topSelectionPixel += fadingEdgeLength; 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return topSelectionPixel; 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move all views upwards so the selected row does not interesect the bottom 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * fading edge (if necessary). 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childInSelectedRow A child in the row that contains the selection 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param topSelectionPixel The topmost pixel we can draw the selection into 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param bottomSelectionPixel The bottommost pixel we can draw the 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selection into 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void adjustForBottomFadingEdge(View childInSelectedRow, 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int topSelectionPixel, int bottomSelectionPixel) { 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Some of the newly selected item extends below the bottom of the 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // list 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childInSelectedRow.getBottom() > bottomSelectionPixel) { 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space available above the selection into which we can 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // scroll upwards 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spaceAbove = childInSelectedRow.getTop() - topSelectionPixel; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space required to bring the bottom of the selected item 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // fully into view 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spaceBelow = childInSelectedRow.getBottom() - bottomSelectionPixel; 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int offset = Math.min(spaceAbove, spaceBelow); 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Now offset the selected item to get it into view 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(-offset); 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Move all views upwards so the selected row does not interesect the top 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * fading edge (if necessary). 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childInSelectedRow A child in the row that contains the selection 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param topSelectionPixel The topmost pixel we can draw the selection into 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param bottomSelectionPixel The bottommost pixel we can draw the 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selection into 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void adjustForTopFadingEdge(View childInSelectedRow, 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int topSelectionPixel, int bottomSelectionPixel) { 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Some of the newly selected item extends above the top of the list 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childInSelectedRow.getTop() < topSelectionPixel) { 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space required to bring the top of the selected item 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // fully into view 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spaceAbove = topSelectionPixel - childInSelectedRow.getTop(); 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space available below the selection into which we can 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // scroll downwards 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spaceBelow = bottomSelectionPixel - childInSelectedRow.getBottom(); 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int offset = Math.min(spaceAbove, spaceBelow); 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Now offset the selected item to get it into view 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(offset); 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 847499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * Smoothly scroll to the specified adapter position. The view will 848499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * scroll such that the indicated position is displayed. 849499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * @param position Scroll to this adapter position. 850499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 851499cb9f516062b654952d282f211bee44c31a3c2Winson Chung @android.view.RemotableViewMethod 852499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public void smoothScrollToPosition(int position) { 853499cb9f516062b654952d282f211bee44c31a3c2Winson Chung super.smoothScrollToPosition(position); 854499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 855499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 856499cb9f516062b654952d282f211bee44c31a3c2Winson Chung /** 857499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * Smoothly scroll to the specified adapter position offset. The view will 858499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * scroll such that the indicated position is displayed. 859499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * @param offset The amount to offset from the adapter position to scroll to. 860499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 861499cb9f516062b654952d282f211bee44c31a3c2Winson Chung @android.view.RemotableViewMethod 862499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public void smoothScrollByOffset(int offset) { 863499cb9f516062b654952d282f211bee44c31a3c2Winson Chung super.smoothScrollByOffset(offset); 864499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 865499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 866499cb9f516062b654952d282f211bee44c31a3c2Winson Chung /** 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fills the grid based on positioning the new selection relative to the old 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selection. The new selection will be placed at, above, or below the 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * location of the new selection depending on how the selection is moving. 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The selection will then be pinned to the visible part of the screen, 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * excluding the edges that are faded. The grid is then filled upwards and 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * downwards from there. 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param delta Which way we are moving 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenTop Where to start drawing children 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenBottom Last pixel where children can be drawn 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that currently has selection 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View moveSelection(int delta, int childrenTop, int childrenBottom) { 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int fadingEdgeLength = getVerticalFadingEdgeLength(); 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int selectedPosition = mSelectedPosition; 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numColumns = mNumColumns; 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int verticalSpacing = mVerticalSpacing; 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oldRowStart; 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rowStart; 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rowEnd = -1; 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldRowStart = (selectedPosition - delta) - ((selectedPosition - delta) % numColumns); 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowStart = selectedPosition - (selectedPosition % numColumns); 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int invertedSelection = mItemCount - 1 - selectedPosition; 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowEnd = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns)); 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowStart = Math.max(0, rowEnd - numColumns + 1); 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invertedSelection = mItemCount - 1 - (selectedPosition - delta); 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldRowStart = mItemCount - 1 - (invertedSelection - (invertedSelection % numColumns)); 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldRowStart = Math.max(0, oldRowStart - numColumns + 1); 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int rowDelta = rowStart - oldRowStart; 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength, rowStart); 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int bottomSelectionPixel = getBottomSelectionPixel(childrenBottom, fadingEdgeLength, 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numColumns, rowStart); 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Possibly changed again in fillUp if we add rows above this one. 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = rowStart; 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View sel; 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View referenceView; 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rowDelta > 0) { 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Case 1: Scrolling down. 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int oldBottom = mReferenceViewInSelectedRow == null ? 0 : 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReferenceViewInSelectedRow.getBottom(); 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = makeRow(mStackFromBottom ? rowEnd : rowStart, oldBottom + verticalSpacing, true); 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project referenceView = mReferenceView; 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustForBottomFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel); 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (rowDelta < 0) { 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Case 2: Scrolling up. 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int oldTop = mReferenceViewInSelectedRow == null ? 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 0 : mReferenceViewInSelectedRow .getTop(); 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = makeRow(mStackFromBottom ? rowEnd : rowStart, oldTop - verticalSpacing, false); 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project referenceView = mReferenceView; 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustForTopFadingEdge(referenceView, topSelectionPixel, bottomSelectionPixel); 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Keep selection where it was 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int oldTop = mReferenceViewInSelectedRow == null ? 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 0 : mReferenceViewInSelectedRow .getTop(); 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = makeRow(mStackFromBottom ? rowEnd : rowStart, oldTop, true); 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project referenceView = mReferenceView; 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(rowStart - numColumns, referenceView.getTop() - verticalSpacing); 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(rowStart + numColumns, referenceView.getBottom() + verticalSpacing); 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(rowEnd + numColumns, referenceView.getBottom() + verticalSpacing); 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(rowStart - 1, referenceView.getTop() - verticalSpacing); 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sel; 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 963edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski private boolean determineColumns(int availableSpace) { 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int requestedHorizontalSpacing = mRequestedHorizontalSpacing; 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int stretchMode = mStretchMode; 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int requestedColumnWidth = mRequestedColumnWidth; 967edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski boolean didNotInitiallyFit = false; 96899441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mRequestedNumColumns == AUTO_FIT) { 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (requestedColumnWidth > 0) { 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Client told us to pick the number of columns 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNumColumns = (availableSpace + requestedHorizontalSpacing) / 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (requestedColumnWidth + requestedHorizontalSpacing); 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Just make up a number if we don't have enough info 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNumColumns = 2; 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We picked the columns 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNumColumns = mRequestedNumColumns; 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 98299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mNumColumns <= 0) { 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNumColumns = 1; 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (stretchMode) { 98899441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas case NO_STRETCH: 98999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas // Nobody stretches 99099441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas mColumnWidth = requestedColumnWidth; 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHorizontalSpacing = requestedHorizontalSpacing; 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 99499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas default: 99599441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas int spaceLeftOver = availableSpace - (mNumColumns * requestedColumnWidth) 99699441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas - ((mNumColumns - 1) * requestedHorizontalSpacing); 99799441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 99899441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas if (spaceLeftOver < 0) { 99999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas didNotInitiallyFit = true; 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 100299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas switch (stretchMode) { 100399441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas case STRETCH_COLUMN_WIDTH: 100499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas // Stretch the columns 100599441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas mColumnWidth = requestedColumnWidth + spaceLeftOver / mNumColumns; 100699441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas mHorizontalSpacing = requestedHorizontalSpacing; 100799441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas break; 100899441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 100999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas case STRETCH_SPACING: 101099441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas // Stretch the spacing between columns 101199441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas mColumnWidth = requestedColumnWidth; 101299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas if (mNumColumns > 1) { 101399441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas mHorizontalSpacing = requestedHorizontalSpacing 101499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas + spaceLeftOver / (mNumColumns - 1); 101599441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas } else { 101699441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas mHorizontalSpacing = requestedHorizontalSpacing + spaceLeftOver; 101799441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas } 101899441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas break; 101999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 102099441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas case STRETCH_SPACING_UNIFORM: 102199441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas // Stretch the spacing between columns 102299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas mColumnWidth = requestedColumnWidth; 102399441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas if (mNumColumns > 1) { 102499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas mHorizontalSpacing = requestedHorizontalSpacing 102599441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas + spaceLeftOver / (mNumColumns + 1); 102699441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas } else { 102799441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas mHorizontalSpacing = requestedHorizontalSpacing + spaceLeftOver; 102899441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas } 102999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas break; 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 103299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas break; 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1034edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski return didNotInitiallyFit; 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Sets up mListPadding 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onMeasure(widthMeasureSpec, heightMeasureSpec); 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int widthMode = MeasureSpec.getMode(widthMeasureSpec); 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int heightMode = MeasureSpec.getMode(heightMeasureSpec); 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int widthSize = MeasureSpec.getSize(widthMeasureSpec); 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int heightSize = MeasureSpec.getSize(heightMeasureSpec); 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (widthMode == MeasureSpec.UNSPECIFIED) { 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mColumnWidth > 0) { 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widthSize = mColumnWidth + mListPadding.left + mListPadding.right; 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widthSize = mListPadding.left + mListPadding.right; 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widthSize += getVerticalScrollbarWidth(); 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 105599441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childWidth = widthSize - mListPadding.left - mListPadding.right; 1057edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski boolean didNotInitiallyFit = determineColumns(childWidth); 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childHeight = 0; 1060189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn int childState = 0; 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mItemCount = mAdapter == null ? 0 : mAdapter.getCount(); 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = mItemCount; 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count > 0) { 106521875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy final View child = obtainView(0, mIsScrap); 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1067aebd28f729fa28016d70551d0372ab7fcd56ee1aAdam Powell AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams(); 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (p == null) { 1069aebd28f729fa28016d70551d0372ab7fcd56ee1aAdam Powell p = (AbsListView.LayoutParams) generateDefaultLayoutParams(); 10704df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project child.setLayoutParams(p); 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.viewType = mAdapter.getItemViewType(0); 107392539d5c75922b430b7f69a14144b6a61045f1f4Alan Viverette p.isEnabled = mAdapter.isEnabled(0); 10740bf88594c43ced48d862d122e3e84967b3b63658Romain Guy p.forceAdd = true; 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childHeightSpec = getChildMeasureSpec( 1077d5dbf4b2a09c9cf2d17fa6af3fdf75d1fb774056Adam Powell MeasureSpec.makeSafeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec), 1078b6824bf58a0cd34395993fa204217e8e246de6fbFilip Gruszczynski MeasureSpec.UNSPECIFIED), 0, p.height); 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childWidthSpec = getChildMeasureSpec( 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width); 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.measure(childWidthSpec, childHeightSpec); 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childHeight = child.getMeasuredHeight(); 1084189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn childState = combineMeasuredStates(childState, child.getMeasuredState()); 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mRecycler.shouldRecycleViewType(p.viewType)) { 1087079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn mRecycler.addScrapView(child, -1); 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 109099441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (heightMode == MeasureSpec.UNSPECIFIED) { 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project heightSize = mListPadding.top + mListPadding.bottom + childHeight + 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getVerticalFadingEdgeLength() * 2; 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (heightMode == MeasureSpec.AT_MOST) { 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ourSize = mListPadding.top + mListPadding.bottom; 109899441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numColumns = mNumColumns; 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i += numColumns) { 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ourSize += childHeight; 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (i + numColumns < count) { 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ourSize += mVerticalSpacing; 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ourSize >= heightSize) { 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ourSize = heightSize; 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project heightSize = ourSize; 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1113189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn if (widthMode == MeasureSpec.AT_MOST && mRequestedNumColumns != AUTO_FIT) { 1114189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn int ourSize = (mRequestedNumColumns*mColumnWidth) 1115189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn + ((mRequestedNumColumns-1)*mHorizontalSpacing) 1116189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn + mListPadding.left + mListPadding.right; 1117edd9508aba83a0e6ed49cce3840783c1c72d1430Adam Lesinski if (ourSize > widthSize || didNotInitiallyFit) { 1118189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn widthSize |= MEASURED_STATE_TOO_SMALL; 1119189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn } 1120189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn } 1121189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setMeasuredDimension(widthSize, heightSize); 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidthMeasureSpec = widthMeasureSpec; 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void attachLayoutAnimationParameters(View child, 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ViewGroup.LayoutParams params, int index, int count) { 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GridLayoutAnimationController.AnimationParameters animationParams = 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters; 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (animationParams == null) { 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project animationParams = new GridLayoutAnimationController.AnimationParameters(); 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project params.layoutAnimationParameters = animationParams; 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project animationParams.count = count; 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project animationParams.index = index; 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project animationParams.columnsCount = mNumColumns; 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project animationParams.rowsCount = count / mNumColumns; 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project animationParams.column = index % mNumColumns; 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project animationParams.row = index / mNumColumns; 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int invertedIndex = count - 1 - index; 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project animationParams.column = mNumColumns - 1 - (invertedIndex % mNumColumns); 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project animationParams.row = animationParams.rowsCount - 1 - invertedIndex / mNumColumns; 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void layoutChildren() { 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean blockLayoutRequests = mBlockLayoutRequests; 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!blockLayoutRequests) { 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBlockLayoutRequests = true; 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.layoutChildren(); 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAdapter == null) { 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetList(); 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childrenTop = mListPadding.top; 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childrenBottom = mBottom - mTop - mListPadding.bottom; 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childCount = getChildCount(); 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index; 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int delta = 0; 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View sel; 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View oldSel = null; 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View oldFirst = null; 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View newSel = null; 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remember stuff we will need down below 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mLayoutMode) { 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SET_SELECTION: 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = mNextSelectedPosition - mFirstPosition; 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index >= 0 && index < childCount) { 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newSel = getChildAt(index); 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_FORCE_TOP: 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_FORCE_BOTTOM: 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SPECIFIC: 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SYNC: 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_MOVE_SELECTION: 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mNextSelectedPosition >= 0) { 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta = mNextSelectedPosition - mSelectedPosition; 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remember the previously selected view 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = mSelectedPosition - mFirstPosition; 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index >= 0 && index < childCount) { 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldSel = getChildAt(index); 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remember the previous first child 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldFirst = getChildAt(0); 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean dataChanged = mDataChanged; 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dataChanged) { 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleDataChanged(); 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Handle the empty set by removing all views that are visible 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and calling it a day 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mItemCount == 0) { 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetList(); 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectedPositionInt(mNextSelectedPosition); 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12283e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null; 12293e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette View accessibilityFocusLayoutRestoreView = null; 12303e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette int accessibilityFocusPosition = INVALID_POSITION; 12313e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette 12323e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette // Remember which child, if any, had accessibility focus. This must 12333e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette // occur before recycling any views, since that will clear 12343e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette // accessibility focus. 12353e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette final ViewRootImpl viewRootImpl = getViewRootImpl(); 12363e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette if (viewRootImpl != null) { 12373e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette final View focusHost = viewRootImpl.getAccessibilityFocusedHost(); 12383e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette if (focusHost != null) { 12393e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette final View focusChild = getAccessibilityFocusedChild(focusHost); 12403e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette if (focusChild != null) { 12413e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette if (!dataChanged || focusChild.hasTransientState() 12423e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette || mAdapterHasStableIds) { 12433e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette // The views won't be changing, so try to maintain 12443e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette // focus on the current host and virtual view. 12453e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette accessibilityFocusLayoutRestoreView = focusHost; 12463e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette accessibilityFocusLayoutRestoreNode = viewRootImpl 12473e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette .getAccessibilityFocusedVirtualView(); 12483e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette } 12493e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette 12503e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette // Try to maintain focus at the same position. 12513e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette accessibilityFocusPosition = getPositionForView(focusChild); 12523e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette } 12533e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette } 12545d565faab21324862fa24490f116424e1b668b1dAlan Viverette } 12555d565faab21324862fa24490f116424e1b668b1dAlan Viverette 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Pull all children into the RecycleBin. 12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // These views will be reused if possible 12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int firstPosition = mFirstPosition; 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final RecycleBin recycleBin = mRecycler; 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dataChanged) { 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < childCount; i++) { 1263079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn recycleBin.addScrapView(getChildAt(i), firstPosition+i); 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recycleBin.fillActiveViews(childCount, firstPosition); 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Clear out old views 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project detachAllViewsFromParent(); 1271539ee8716b4f81260bab2e9f3dc5d88d81c99985Adam Powell recycleBin.removeSkippedScrap(); 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mLayoutMode) { 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SET_SELECTION: 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newSel != null) { 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillFromSelection(newSel.getTop(), childrenTop, childrenBottom); 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillSelection(childrenTop, childrenBottom); 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_FORCE_TOP: 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = 0; 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillFromTop(childrenTop); 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_FORCE_BOTTOM: 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillUp(mItemCount - 1, childrenBottom); 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SPECIFIC: 12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillSpecific(mSelectedPosition, mSpecificTop); 12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SYNC: 12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillSpecific(mSyncPosition, mSpecificTop); 12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_MOVE_SELECTION: 12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Move the selection relative to its old position 12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = moveSelection(delta, childrenTop, childrenBottom); 12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childCount == 0) { 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 130391c8613679959a5fde4f72fe6dd80023d9a1a9e7Romain Guy setSelectedPositionInt(mAdapter == null || isInTouchMode() ? 130491c8613679959a5fde4f72fe6dd80023d9a1a9e7Romain Guy INVALID_POSITION : 0); 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillFromTop(childrenTop); 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int last = mItemCount - 1; 130891c8613679959a5fde4f72fe6dd80023d9a1a9e7Romain Guy setSelectedPositionInt(mAdapter == null || isInTouchMode() ? 130991c8613679959a5fde4f72fe6dd80023d9a1a9e7Romain Guy INVALID_POSITION : last); 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillFromBottom(last, childrenBottom); 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSelectedPosition >= 0 && mSelectedPosition < mItemCount) { 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillSpecific(mSelectedPosition, oldSel == null ? 13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childrenTop : oldSel.getTop()); 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mFirstPosition < mItemCount) { 13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillSpecific(mFirstPosition, oldFirst == null ? 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childrenTop : oldFirst.getTop()); 13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillSpecific(0, childrenTop); 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Flush any cached views that did not get reused above 13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recycleBin.scrapActiveViews(); 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sel != null) { 1330079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn positionSelector(INVALID_POSITION, sel); 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSelectedTop = sel.getTop(); 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1333e3c433aa457138425e514494e4d06590076a1d07Alan Viverette final boolean inTouchMode = mTouchMode > TOUCH_MODE_DOWN 1334e3c433aa457138425e514494e4d06590076a1d07Alan Viverette && mTouchMode < TOUCH_MODE_SCROLL; 1335e3c433aa457138425e514494e4d06590076a1d07Alan Viverette if (inTouchMode) { 1336e3c433aa457138425e514494e4d06590076a1d07Alan Viverette // If the user's finger is down, select the motion position. 1337e3c433aa457138425e514494e4d06590076a1d07Alan Viverette final View child = getChildAt(mMotionPosition - mFirstPosition); 1338e3c433aa457138425e514494e4d06590076a1d07Alan Viverette if (child != null) { 1339e3c433aa457138425e514494e4d06590076a1d07Alan Viverette positionSelector(mMotionPosition, child); 1340e3c433aa457138425e514494e4d06590076a1d07Alan Viverette } 1341e3c433aa457138425e514494e4d06590076a1d07Alan Viverette } else if (mSelectedPosition != INVALID_POSITION) { 1342e3c433aa457138425e514494e4d06590076a1d07Alan Viverette // If we had previously positioned the selector somewhere, 1343e3c433aa457138425e514494e4d06590076a1d07Alan Viverette // put it back there. It might not match up with the data, 1344e3c433aa457138425e514494e4d06590076a1d07Alan Viverette // but it's transitioning out so it's not a big deal. 1345e3c433aa457138425e514494e4d06590076a1d07Alan Viverette final View child = getChildAt(mSelectorPosition - mFirstPosition); 1346e3c433aa457138425e514494e4d06590076a1d07Alan Viverette if (child != null) { 1347e3c433aa457138425e514494e4d06590076a1d07Alan Viverette positionSelector(mSelectorPosition, child); 1348e3c433aa457138425e514494e4d06590076a1d07Alan Viverette } 1349e3c433aa457138425e514494e4d06590076a1d07Alan Viverette } else { 1350e3c433aa457138425e514494e4d06590076a1d07Alan Viverette // Otherwise, clear selection. 1351e3c433aa457138425e514494e4d06590076a1d07Alan Viverette mSelectedTop = 0; 1352e3c433aa457138425e514494e4d06590076a1d07Alan Viverette mSelectorRect.setEmpty(); 1353e3c433aa457138425e514494e4d06590076a1d07Alan Viverette } 13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13563e14162fc655e7a0dae61318911f3e29c07d0bf0Alan Viverette // Attempt to restore accessibility focus, if necessary. 13572e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette if (viewRootImpl != null) { 13582e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette final View newAccessibilityFocusedView = viewRootImpl.getAccessibilityFocusedHost(); 13592e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette if (newAccessibilityFocusedView == null) { 13602e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette if (accessibilityFocusLayoutRestoreView != null 13612e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette && accessibilityFocusLayoutRestoreView.isAttachedToWindow()) { 13622e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette final AccessibilityNodeProvider provider = 13632e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette accessibilityFocusLayoutRestoreView.getAccessibilityNodeProvider(); 13642e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette if (accessibilityFocusLayoutRestoreNode != null && provider != null) { 13652e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId( 13662e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette accessibilityFocusLayoutRestoreNode.getSourceNodeId()); 13672e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette provider.performAction(virtualViewId, 13682e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null); 13692e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette } else { 13702e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette accessibilityFocusLayoutRestoreView.requestAccessibilityFocus(); 13712e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette } 13722e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette } else if (accessibilityFocusPosition != INVALID_POSITION) { 13732e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette // Bound the position within the visible children. 13742e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette final int position = MathUtils.constrain( 13752e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette accessibilityFocusPosition - mFirstPosition, 0, 13762e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette getChildCount() - 1); 13772e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette final View restoreView = getChildAt(position); 13782e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette if (restoreView != null) { 13792e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette restoreView.requestAccessibilityFocus(); 13802e6fc8ca5696367a680656f73c1b9b95648eb6faAlan Viverette } 13815d565faab21324862fa24490f116424e1b668b1dAlan Viverette } 13825d565faab21324862fa24490f116424e1b668b1dAlan Viverette } 13835d565faab21324862fa24490f116424e1b668b1dAlan Viverette } 13845d565faab21324862fa24490f116424e1b668b1dAlan Viverette 13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_NORMAL; 13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataChanged = false; 1387161abf3d44feebb8462f7d0cbee81574d666234bAdam Powell if (mPositionScrollAfterLayout != null) { 1388161abf3d44feebb8462f7d0cbee81574d666234bAdam Powell post(mPositionScrollAfterLayout); 1389161abf3d44feebb8462f7d0cbee81574d666234bAdam Powell mPositionScrollAfterLayout = null; 1390161abf3d44feebb8462f7d0cbee81574d666234bAdam Powell } 13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNeedSync = false; 13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setNextSelectedPositionInt(mSelectedPosition); 13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateScrollIndicators(); 13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mItemCount > 0) { 13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkSelectionChanged(); 13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!blockLayoutRequests) { 14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBlockLayoutRequests = false; 14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 141026489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * Obtains the view and adds it to our list of children. The view can be 141126489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * made fresh, converted from an unused view, or used as is if it was in 141226489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * the recycle bin. 14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 141426489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param position logical position in the list 141526489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param y top or bottom edge of the view to add 141626489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param flow {@code true} to align top edge to y, {@code false} to align 141726489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * bottom edge to y 141826489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param childrenLeft left edge where children should be positioned 141926489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param selected {@code true} if the position is selected, {@code false} 142026489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * otherwise 142126489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param where position at which to add new item in the list 14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return View that was added 14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View makeAndAddView(int position, int y, boolean flow, int childrenLeft, 14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean selected, int where) { 14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mDataChanged) { 142721875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy // Try to use an existing view for this position 142826489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette final View activeView = mRecycler.getActiveView(position); 142926489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette if (activeView != null) { 14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Found it -- we're using an existing child 14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This just needs to be positioned 143226489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette setupChild(activeView, position, y, flow, childrenLeft, selected, true, where); 143326489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette return activeView; 14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make a new view for this position, or convert an unused view if 143826489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette // possible. 143926489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette final View child = obtainView(position, mIsScrap); 14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 144126489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette // This needs to be positioned and measured. 144221875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0], where); 14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return child; 14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 144826489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * Adds a view as a child and make sure it is measured (if necessary) and 14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * positioned properly. 14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 145126489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param child the view to add 145226489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param position the position of this child 145326489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param y the y position relative to which this view will be positioned 145426489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param flowDown {@code true} to align top edge to y, {@code false} to 145526489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * align bottom edge to y 145626489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param childrenLeft left edge where children should be positioned 145726489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param selected {@code true} if the position is selected, {@code false} 145826489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * otherwise 145926489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param isAttachedToWindow {@code true} if the view is already attached 146026489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * to the window, e.g. whether it was reused, or 146126489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * {@code false} otherwise 146226489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette * @param where position at which to add new item in the list 14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 146526489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette private void setupChild(View child, int position, int y, boolean flowDown, int childrenLeft, 146626489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette boolean selected, boolean isAttachedToWindow, int where) { 14675fade8c69aef621312232ef0647502d7a63990b9Romain Guy Trace.traceBegin(Trace.TRACE_TAG_VIEW, "setupGridItem"); 14685fade8c69aef621312232ef0647502d7a63990b9Romain Guy 14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isSelected = selected && shouldShowSelector(); 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean updateChildSelected = isSelected != child.isSelected(); 14713616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy final int mode = mTouchMode; 147226489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL 147326489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette && mMotionPosition == position; 14743616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy final boolean updateChildPressed = isPressed != child.isPressed(); 147526489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette final boolean needToMeasure = !isAttachedToWindow || updateChildSelected 147626489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette || child.isLayoutRequested(); 14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Respect layout params that are already in the view. Otherwise make 14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // some up... 1480aebd28f729fa28016d70551d0372ab7fcd56ee1aAdam Powell AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams(); 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (p == null) { 1482aebd28f729fa28016d70551d0372ab7fcd56ee1aAdam Powell p = (AbsListView.LayoutParams) generateDefaultLayoutParams(); 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.viewType = mAdapter.getItemViewType(position); 148592539d5c75922b430b7f69a14144b6a61045f1f4Alan Viverette p.isEnabled = mAdapter.isEnabled(position); 14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 148726489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette // Set up view state before attaching the view, since we may need to 148826489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette // rely on the jumpDrawablesToCurrentState() call that occurs as part 148926489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette // of view attachment. 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (updateChildSelected) { 14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.setSelected(isSelected); 14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isSelected) { 14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestFocus(); 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14973616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy if (updateChildPressed) { 14983616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy child.setPressed(isPressed); 14993616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy } 15003616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy 1501f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) { 1502f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell if (child instanceof Checkable) { 1503f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell ((Checkable) child).setChecked(mCheckStates.get(position)); 1504d0fa371f276fde32d81c037006941bc93da0bb03Dianne Hackborn } else if (getContext().getApplicationInfo().targetSdkVersion 1505d0fa371f276fde32d81c037006941bc93da0bb03Dianne Hackborn >= android.os.Build.VERSION_CODES.HONEYCOMB) { 1506d0fa371f276fde32d81c037006941bc93da0bb03Dianne Hackborn child.setActivated(mCheckStates.get(position)); 1507f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell } 1508f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell } 1509f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell 151026489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette if (isAttachedToWindow && !p.forceAdd) { 151126489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette attachViewToParent(child, where, p); 151226489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette 151326489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette // If the view isn't attached, or if it's attached but for a different 151426489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette // position, then jump the drawables. 151526489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette if (!isAttachedToWindow 151626489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette || (((AbsListView.LayoutParams) child.getLayoutParams()).scrappedFromPosition) 151726489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette != position) { 151826489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette child.jumpDrawablesToCurrentState(); 151926489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette } 152026489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette } else { 152126489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette p.forceAdd = false; 152226489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette addViewInLayout(child, where, p, true); 152326489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette } 152426489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette 15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (needToMeasure) { 15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childHeightSpec = ViewGroup.getChildMeasureSpec( 15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), 0, p.height); 15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childWidthSpec = ViewGroup.getChildMeasureSpec( 15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width); 15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.measure(childWidthSpec, childHeightSpec); 15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cleanupLayoutState(child); 15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int w = child.getMeasuredWidth(); 15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int h = child.getMeasuredHeight(); 15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childLeft; 154026489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette final int childTop = flowDown ? y : y - h; 15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1542e56ffdc7b31b0937628609cc3bbaa15879023569Fabrice Di Meglio final int layoutDirection = getLayoutDirection(); 1543c0053223bedf33581b0830fb87be32c1f26e5372Fabrice Di Meglio final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection); 15446a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) { 15456a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio case Gravity.LEFT: 15466a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio childLeft = childrenLeft; 15476a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio break; 15486a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio case Gravity.CENTER_HORIZONTAL: 15496a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio childLeft = childrenLeft + ((mColumnWidth - w) / 2); 15506a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio break; 15516a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio case Gravity.RIGHT: 15526a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio childLeft = childrenLeft + mColumnWidth - w; 15536a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio break; 15546a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio default: 15556a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio childLeft = childrenLeft; 15566a03640539405afbdefe72894759281b98aa6e6fFabrice Di Meglio break; 15579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (needToMeasure) { 15609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childRight = childLeft + w; 15619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childBottom = childTop + h; 15629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.layout(childLeft, childTop, childRight, childBottom); 15639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 15649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.offsetLeftAndRight(childLeft - child.getLeft()); 15659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.offsetTopAndBottom(childTop - child.getTop()); 15669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 156826489e1688633ee270ff1469d0df38c90bbdf674Alan Viverette if (mCachingStarted && !child.isDrawingCacheEnabled()) { 15699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.setDrawingCacheEnabled(true); 15709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1571079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn 15725fade8c69aef621312232ef0647502d7a63990b9Romain Guy Trace.traceEnd(Trace.TRACE_TAG_VIEW); 15739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 15769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the currently selected item 157799441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * 15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position Index (starting at 0) of the data item to be selected. 157999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * 15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If in touch mode, the item will not be selected but it will still be positioned 15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * appropriately. 15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSelection(int position) { 15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isInTouchMode()) { 15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setNextSelectedPositionInt(position); 15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResurrectToPosition = position; 15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_SET_SELECTION; 15911fa179ef41c06bd19da70fd9bf95741238791940Adam Powell if (mPositionScroller != null) { 15921fa179ef41c06bd19da70fd9bf95741238791940Adam Powell mPositionScroller.stop(); 15931fa179ef41c06bd19da70fd9bf95741238791940Adam Powell } 15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(); 15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Makes the item at the supplied position selected. 15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position the position of the new selection 16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void setSelectionInt(int position) { 1604f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron int previousSelectedPosition = mNextSelectedPosition; 1605f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron 16061fa179ef41c06bd19da70fd9bf95741238791940Adam Powell if (mPositionScroller != null) { 16071fa179ef41c06bd19da70fd9bf95741238791940Adam Powell mPositionScroller.stop(); 16081fa179ef41c06bd19da70fd9bf95741238791940Adam Powell } 16091fa179ef41c06bd19da70fd9bf95741238791940Adam Powell 16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setNextSelectedPositionInt(position); 16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layoutChildren(); 161299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 161399441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas final int next = mStackFromBottom ? mItemCount - 1 - mNextSelectedPosition : 1614f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron mNextSelectedPosition; 1615f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron final int previous = mStackFromBottom ? mItemCount - 1 1616f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron - previousSelectedPosition : previousSelectedPosition; 1617f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron 1618f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron final int nextRow = next / mNumColumns; 1619f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron final int previousRow = previous / mNumColumns; 1620f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron 1621f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron if (nextRow != previousRow) { 1622f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron awakenScrollBars(); 1623f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron } 1624f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron 16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return commonKey(keyCode, 1, event); 16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return commonKey(keyCode, repeatCount, event); 16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return commonKey(keyCode, 1, event); 16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean commonKey(int keyCode, int count, KeyEvent event) { 16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAdapter == null) { 16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDataChanged) { 16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layoutChildren(); 16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean handled = false; 16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int action = event.getAction(); 1653aa1a94daaa59e98303fdeb1c3066b60a58755dffMichael Wright if (KeyEvent.isConfirmKey(keyCode) 1654759f9fed70adf0f6e955b0ecca5b21ab5a42ac0dMichael Wright && event.hasNoModifiers() && action != KeyEvent.ACTION_UP) { 1655aa1a94daaa59e98303fdeb1c3066b60a58755dffMichael Wright handled = resurrectSelectionIfNeeded(); 1656aa1a94daaa59e98303fdeb1c3066b60a58755dffMichael Wright if (!handled && event.getRepeatCount() == 0 && getChildCount() > 0) { 1657aa1a94daaa59e98303fdeb1c3066b60a58755dffMichael Wright keyPressed(); 1658aa1a94daaa59e98303fdeb1c3066b60a58755dffMichael Wright handled = true; 1659aa1a94daaa59e98303fdeb1c3066b60a58755dffMichael Wright } 1660aa1a94daaa59e98303fdeb1c3066b60a58755dffMichael Wright } 16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1662aa1a94daaa59e98303fdeb1c3066b60a58755dffMichael Wright if (!handled && action != KeyEvent.ACTION_UP) { 16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (keyCode) { 16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case KeyEvent.KEYCODE_DPAD_LEFT: 16654e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 16668d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_LEFT); 16674e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case KeyEvent.KEYCODE_DPAD_RIGHT: 16714e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 16728d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_RIGHT); 16734e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case KeyEvent.KEYCODE_DPAD_UP: 16774e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 16788d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_UP); 16794e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) { 16808d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP); 16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case KeyEvent.KEYCODE_DPAD_DOWN: 16854e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 16868d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_DOWN); 16874e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) { 16888d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN); 16899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16924e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case KeyEvent.KEYCODE_PAGE_UP: 16934e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 16948d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_UP); 16954e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) { 16968d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP); 16974e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 16984e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown break; 16994e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 17004e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case KeyEvent.KEYCODE_PAGE_DOWN: 17014e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 17028d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_DOWN); 17034e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) { 17048d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN); 17054e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 17064e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown break; 17074e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 17084e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case KeyEvent.KEYCODE_MOVE_HOME: 17094e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 17108d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP); 17114e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 17124e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown break; 17134e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 17144e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case KeyEvent.KEYCODE_MOVE_END: 17154e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 17168d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN); 17174e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 17184e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown break; 17194e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 17204e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case KeyEvent.KEYCODE_TAB: 17218c8ac8125ac93e87733994190bb54925d188bdc1Evan Rosky // TODO: Sometimes it is useful to be able to TAB through the items in 17224e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // a GridView sequentially. Unfortunately this can create an 17234e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // asymmetry in TAB navigation order unless the list selection 17244e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // always reverts to the top or bottom when receiving TAB focus from 17258c8ac8125ac93e87733994190bb54925d188bdc1Evan Rosky // another widget. 17268c8ac8125ac93e87733994190bb54925d188bdc1Evan Rosky if (event.hasNoModifiers()) { 17278c8ac8125ac93e87733994190bb54925d188bdc1Evan Rosky handled = resurrectSelectionIfNeeded() 17288c8ac8125ac93e87733994190bb54925d188bdc1Evan Rosky || sequenceScroll(FOCUS_FORWARD); 17298c8ac8125ac93e87733994190bb54925d188bdc1Evan Rosky } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) { 17308c8ac8125ac93e87733994190bb54925d188bdc1Evan Rosky handled = resurrectSelectionIfNeeded() 17318c8ac8125ac93e87733994190bb54925d188bdc1Evan Rosky || sequenceScroll(FOCUS_BACKWARD); 17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17378d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown if (handled) { 17388d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown return true; 17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17418d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown if (sendToTextFilter(keyCode, count, event)) { 17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 17438d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown } 17448d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown 17458d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown switch (action) { 17468d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown case KeyEvent.ACTION_DOWN: 17478d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown return super.onKeyDown(keyCode, event); 17488d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown case KeyEvent.ACTION_UP: 17498d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown return super.onKeyUp(keyCode, event); 17508d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown case KeyEvent.ACTION_MULTIPLE: 17518d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown return super.onKeyMultiple(keyCode, count, event); 17528d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown default: 17538d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown return false; 17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scrolls up or down by the number of items currently present on screen. 17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN} 17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return whether selection was moved 17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean pageScroll(int direction) { 17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextPage = -1; 17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == FOCUS_UP) { 176764d50a67f44f6f8627b6d5203f0e3b26dc4f71e5Romain Guy nextPage = Math.max(0, mSelectedPosition - getChildCount()); 17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (direction == FOCUS_DOWN) { 176964d50a67f44f6f8627b6d5203f0e3b26dc4f71e5Romain Guy nextPage = Math.min(mItemCount - 1, mSelectedPosition + getChildCount()); 17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextPage >= 0) { 17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectionInt(nextPage); 17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 1775f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron awakenScrollBars(); 17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Go to the last or first item if possible. 17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN}. 17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether selection was moved. 17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean fullScroll(int direction) { 17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean moved = false; 17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == FOCUS_UP) { 17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_SET_SELECTION; 17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectionInt(0); 17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project moved = true; 17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (direction == FOCUS_DOWN) { 17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_SET_SELECTION; 17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectionInt(mItemCount - 1); 17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project moved = true; 18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 180299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 1803f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron if (moved) { 1804f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron awakenScrollBars(); 1805f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron } 18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return moved; 18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scrolls to the next or previous item, horizontally or vertically. 18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction either {@link View#FOCUS_LEFT}, {@link View#FOCUS_RIGHT}, 18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN} 18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return whether selection was moved 18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean arrowScroll(int direction) { 18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int selectedPosition = mSelectedPosition; 18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numColumns = mNumColumns; 18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int startOfRowPos; 18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int endOfRowPos; 18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean moved = false; 18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startOfRowPos = (selectedPosition / numColumns) * numColumns; 18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endOfRowPos = Math.min(startOfRowPos + numColumns - 1, mItemCount - 1); 18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int invertedSelection = mItemCount - 1 - selectedPosition; 18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endOfRowPos = mItemCount - 1 - (invertedSelection / numColumns) * numColumns; 18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startOfRowPos = Math.max(0, endOfRowPos - numColumns + 1); 18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (direction) { 18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case FOCUS_UP: 18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startOfRowPos > 0) { 18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_MOVE_SELECTION; 18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectionInt(Math.max(0, selectedPosition - numColumns)); 18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project moved = true; 18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case FOCUS_DOWN: 18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (endOfRowPos < mItemCount - 1) { 18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_MOVE_SELECTION; 18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectionInt(Math.min(selectedPosition + numColumns, mItemCount - 1)); 18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project moved = true; 18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 1851599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson } 1852599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson 1853599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson final boolean isLayoutRtl = isLayoutRtl(); 1854599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson if (selectedPosition > startOfRowPos && ((direction == FOCUS_LEFT && !isLayoutRtl) || 1855599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson (direction == FOCUS_RIGHT && isLayoutRtl))) { 1856599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson mLayoutMode = LAYOUT_MOVE_SELECTION; 1857599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson setSelectionInt(Math.max(0, selectedPosition - 1)); 1858599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson moved = true; 1859599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson } else if (selectedPosition < endOfRowPos && ((direction == FOCUS_LEFT && isLayoutRtl) || 1860599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson (direction == FOCUS_RIGHT && !isLayoutRtl))) { 1861599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson mLayoutMode = LAYOUT_MOVE_SELECTION; 1862599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson setSelectionInt(Math.min(selectedPosition + 1, mItemCount - 1)); 1863599b64f937dc30468344f2cbdd27861431f0f459Jorn Jacobsson moved = true; 18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (moved) { 18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); 18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1871f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron if (moved) { 1872f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron awakenScrollBars(); 1873f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron } 187499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return moved; 18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18784e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown /** 18794e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown * Goes to the next or previous item according to the order set by the 18804e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown * adapter. 18814e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown */ 18824e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown boolean sequenceScroll(int direction) { 18834e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown int selectedPosition = mSelectedPosition; 18844e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown int numColumns = mNumColumns; 18854e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown int count = mItemCount; 18864e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 18874e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown int startOfRow; 18884e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown int endOfRow; 18894e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (!mStackFromBottom) { 18904e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown startOfRow = (selectedPosition / numColumns) * numColumns; 18914e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown endOfRow = Math.min(startOfRow + numColumns - 1, count - 1); 18924e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } else { 18934e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown int invertedSelection = count - 1 - selectedPosition; 18944e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown endOfRow = count - 1 - (invertedSelection / numColumns) * numColumns; 18954e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown startOfRow = Math.max(0, endOfRow - numColumns + 1); 18964e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 18974e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 18984e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown boolean moved = false; 18994e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown boolean showScroll = false; 19004e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown switch (direction) { 19014e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case FOCUS_FORWARD: 19024e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (selectedPosition < count - 1) { 19034e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // Move to the next item. 19044e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown mLayoutMode = LAYOUT_MOVE_SELECTION; 19054e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown setSelectionInt(selectedPosition + 1); 19064e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown moved = true; 19074e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // Show the scrollbar only if changing rows. 19084e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown showScroll = selectedPosition == endOfRow; 19094e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 19104e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown break; 19114e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 19124e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case FOCUS_BACKWARD: 19134e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (selectedPosition > 0) { 19144e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // Move to the previous item. 19154e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown mLayoutMode = LAYOUT_MOVE_SELECTION; 19164e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown setSelectionInt(selectedPosition - 1); 19174e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown moved = true; 19184e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // Show the scrollbar only if changing rows. 19194e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown showScroll = selectedPosition == startOfRow; 19204e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 19214e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown break; 19224e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 19234e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 19244e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (moved) { 19254e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); 19264e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown invokeOnItemScrollListener(); 19274e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 19284e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 19294e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (showScroll) { 19304e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown awakenScrollBars(); 19314e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 19324e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 19334e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown return moved; 19344e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 19354e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { 19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); 19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int closestChildIndex = -1; 19419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (gainFocus && previouslyFocusedRect != null) { 19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project previouslyFocusedRect.offset(mScrollX, mScrollY); 19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // figure out which item should be selected based on previously 19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // focused rect 19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Rect otherRect = mTempRect; 19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int minDistance = Integer.MAX_VALUE; 19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childCount = getChildCount(); 19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < childCount; i++) { 19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // only consider view's on appropriate edge of grid 19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isCandidateSelection(i, direction)) { 19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View other = getChildAt(i); 19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project other.getDrawingRect(otherRect); 19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetDescendantRectToMyCoords(other, otherRect); 19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int distance = getDistance(previouslyFocusedRect, otherRect, direction); 19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (distance < minDistance) { 19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project minDistance = distance; 19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closestChildIndex = i; 19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (closestChildIndex >= 0) { 19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(closestChildIndex + mFirstPosition); 19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(); 19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Is childIndex a candidate for next focus given the direction the focus 19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * change is coming from? 19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childIndex The index to check. 19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction The direction, one of 19794e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown * {FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD, FOCUS_BACKWARD} 19809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether childIndex is a candidate. 19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 19829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isCandidateSelection(int childIndex, int direction) { 19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = getChildCount(); 19849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int invertedIndex = count - 1 - childIndex; 19859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rowStart; 19879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rowEnd; 19889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 19909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowStart = childIndex - (childIndex % mNumColumns); 19918c8ac8125ac93e87733994190bb54925d188bdc1Evan Rosky rowEnd = Math.min(rowStart + mNumColumns - 1, count); 19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowEnd = count - 1 - (invertedIndex - (invertedIndex % mNumColumns)); 19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rowStart = Math.max(0, rowEnd - mNumColumns + 1); 19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (direction) { 19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case View.FOCUS_RIGHT: 19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // coming from left, selection is only valid if it is on left 20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // edge 20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return childIndex == rowStart; 20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case View.FOCUS_DOWN: 20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // coming from top; only valid if in top row 20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return rowStart == 0; 20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case View.FOCUS_LEFT: 20069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // coming from right, must be on right edge 20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return childIndex == rowEnd; 20089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case View.FOCUS_UP: 20099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // coming from bottom, need to be in last row 20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return rowEnd == count - 1; 20114e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case View.FOCUS_FORWARD: 20124e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // coming from top-left, need to be first in top row 20134e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown return childIndex == rowStart && rowStart == 0; 20144e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case View.FOCUS_BACKWARD: 20154e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // coming from bottom-right, need to be last in bottom row 20164e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown return childIndex == rowEnd && rowEnd == count - 1; 20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("direction must be one of " 20194e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown + "{FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, " 20204e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown + "FOCUS_FORWARD, FOCUS_BACKWARD}."); 20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 20250b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * Set the gravity for this grid. Gravity describes how the child views 20260b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * are horizontally aligned. Defaults to Gravity.LEFT 20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param gravity the gravity to apply to this grid's children 20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GridView_gravity 20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGravity(int gravity) { 20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mGravity != gravity) { 20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGravity = gravity; 20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayoutIfNecessary(); 20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 20400b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * Describes how the child views are horizontally aligned. Defaults to Gravity.LEFT 20410b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 20420b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @return the gravity that will be applied to this grid's children 20430b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 20440b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @attr ref android.R.styleable#GridView_gravity 20450b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell */ 20460b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell public int getGravity() { 20470b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell return mGravity; 20480b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell } 20490b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell 20500b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell /** 20519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the amount of horizontal (x) spacing to place between each item 20529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the grid. 20539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 20549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param horizontalSpacing The amount of horizontal space between items, 20559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in pixels. 20569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 20579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GridView_horizontalSpacing 20589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 20599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setHorizontalSpacing(int horizontalSpacing) { 20609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (horizontalSpacing != mRequestedHorizontalSpacing) { 20619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRequestedHorizontalSpacing = horizontalSpacing; 20629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayoutIfNecessary(); 20639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20660b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell /** 20670b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * Returns the amount of horizontal spacing currently used between each item in the grid. 20680b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 20690b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * <p>This is only accurate for the current layout. If {@link #setHorizontalSpacing(int)} 20700b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * has been called but layout is not yet complete, this method may return a stale value. 20710b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * To get the horizontal spacing that was explicitly requested use 20720b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * {@link #getRequestedHorizontalSpacing()}.</p> 20730b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 20740b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @return Current horizontal spacing between each item in pixels 20750b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 20760b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @see #setHorizontalSpacing(int) 20770b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @see #getRequestedHorizontalSpacing() 20780b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 20790b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @attr ref android.R.styleable#GridView_horizontalSpacing 20800b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell */ 20810b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell public int getHorizontalSpacing() { 20820b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell return mHorizontalSpacing; 20830b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell } 20840b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell 20850b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell /** 20860b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * Returns the requested amount of horizontal spacing between each item in the grid. 20870b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 20880b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * <p>The value returned may have been supplied during inflation as part of a style, 20890b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * the default GridView style, or by a call to {@link #setHorizontalSpacing(int)}. 20900b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * If layout is not yet complete or if GridView calculated a different horizontal spacing 20910b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * from what was requested, this may return a different value from 20920b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * {@link #getHorizontalSpacing()}.</p> 20930b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 20940b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @return The currently requested horizontal spacing between items, in pixels 20950b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 20960b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @see #setHorizontalSpacing(int) 20970b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @see #getHorizontalSpacing() 20980b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 20990b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @attr ref android.R.styleable#GridView_horizontalSpacing 21000b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell */ 21010b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell public int getRequestedHorizontalSpacing() { 21020b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell return mRequestedHorizontalSpacing; 21030b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell } 21049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 21069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the amount of vertical (y) spacing to place between each item 21079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in the grid. 21089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 21099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param verticalSpacing The amount of vertical space between items, 21109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * in pixels. 21119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 21120b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @see #getVerticalSpacing() 21130b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GridView_verticalSpacing 21159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 21169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setVerticalSpacing(int verticalSpacing) { 21179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (verticalSpacing != mVerticalSpacing) { 21189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mVerticalSpacing = verticalSpacing; 21199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayoutIfNecessary(); 21209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 21240b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * Returns the amount of vertical spacing between each item in the grid. 21250b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21260b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @return The vertical spacing between items in pixels 21270b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21280b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @see #setVerticalSpacing(int) 21290b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21300b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @attr ref android.R.styleable#GridView_verticalSpacing 21310b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell */ 21320b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell public int getVerticalSpacing() { 21330b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell return mVerticalSpacing; 21340b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell } 21350b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell 21360b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell /** 21379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Control how items are stretched to fill their space. 21389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 21399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param stretchMode Either {@link #NO_STRETCH}, 21409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #STRETCH_SPACING}, {@link #STRETCH_SPACING_UNIFORM}, or {@link #STRETCH_COLUMN_WIDTH}. 21419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 21429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GridView_stretchMode 21439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2144d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye public void setStretchMode(@StretchMode int stretchMode) { 21459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (stretchMode != mStretchMode) { 21469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStretchMode = stretchMode; 21479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayoutIfNecessary(); 21489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2151d9273d6f289d9b55da3fd0db2f659fdfb48106a8Tor Norbye @StretchMode 21529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStretchMode() { 21539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mStretchMode; 21549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 21579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the width of columns in the grid. 21589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 21599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param columnWidth The column width, in pixels. 21609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 21619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GridView_columnWidth 21629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 21639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setColumnWidth(int columnWidth) { 21649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (columnWidth != mRequestedColumnWidth) { 21659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRequestedColumnWidth = columnWidth; 21669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayoutIfNecessary(); 21679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 21710b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * Return the width of a column in the grid. 21720b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21730b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * <p>This may not be valid yet if a layout is pending.</p> 21740b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21750b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @return The column width in pixels 21760b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21770b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @see #setColumnWidth(int) 21780b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @see #getRequestedColumnWidth() 21790b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21800b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @attr ref android.R.styleable#GridView_columnWidth 21810b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell */ 21820b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell public int getColumnWidth() { 21830b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell return mColumnWidth; 21840b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell } 21850b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell 21860b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell /** 21870b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * Return the requested width of a column in the grid. 21880b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21890b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * <p>This may not be the actual column width used. Use {@link #getColumnWidth()} 21900b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * to retrieve the current real width of a column.</p> 21910b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21920b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @return The requested column width in pixels 21930b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21940b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @see #setColumnWidth(int) 21950b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @see #getColumnWidth() 21960b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * 21970b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell * @attr ref android.R.styleable#GridView_columnWidth 21980b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell */ 21990b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell public int getRequestedColumnWidth() { 22000b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell return mRequestedColumnWidth; 22010b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell } 22020b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell 22030b7413d5d6239b7bc43816bea5187b323a633b11Adam Powell /** 22049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Set the number of columns in the grid 22059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 22069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param numColumns The desired number of columns. 22079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 22089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#GridView_numColumns 22099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 22109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setNumColumns(int numColumns) { 22119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (numColumns != mRequestedNumColumns) { 22129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRequestedNumColumns = numColumns; 22139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayoutIfNecessary(); 22149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 221699441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 22178d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein /** 221899441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * Get the number of columns in the grid. 22198d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein * Returns {@link #AUTO_FIT} if the Grid has never been laid out. 22208d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein * 22218d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein * @attr ref android.R.styleable#GridView_numColumns 222299441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas * 22238d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein * @see #setNumColumns(int) 22248d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein */ 22258d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein @ViewDebug.ExportedProperty 222699441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas public int getNumColumns() { 22278d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein return mNumColumns; 22288d9db8e4c774bb75bc8c08cc5309a7c0712ce017Andrew Sapperstein } 22299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 22319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Make sure views are touching the top or bottom edge, as appropriate for 22329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * our gravity 22339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 22349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void adjustViewsUpOrDown() { 22359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childCount = getChildCount(); 22369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childCount > 0) { 22389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int delta; 22399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child; 22409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 22429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Uh-oh -- we came up short. Slide all views up to make them 22439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // align with the top 22449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child = getChildAt(0); 22459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta = child.getTop() - mListPadding.top; 22469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition != 0) { 22479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It's OK to have some space above the first item if it is 22489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // part of the vertical spacing 22499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta -= mVerticalSpacing; 22509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (delta < 0) { 22529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We only are looking to see if we are too low, not too high 22539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta = 0; 22549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 22569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we are too high, slide all views down to align with bottom 22579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child = getChildAt(childCount - 1); 22589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta = child.getBottom() - (getHeight() - mListPadding.bottom); 225999441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 22609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition + childCount < mItemCount) { 22619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It's OK to have some space below the last item if it is 22629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // part of the vertical spacing 22639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta += mVerticalSpacing; 22649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 226599441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 22669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (delta > 0) { 22679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We only are looking to see if we are too high, not too low 22689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta = 0; 22699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (delta != 0) { 22739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(-delta); 22749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 227799441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 22789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 22799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int computeVerticalScrollExtent() { 22809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = getChildCount(); 22819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count > 0) { 22829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numColumns = mNumColumns; 22839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int rowCount = (count + numColumns - 1) / numColumns; 228499441c5d7da45c10b729185852be97cbb0bdc8d5Aurimas Liutikas 22859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int extent = rowCount * 100; 22869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View view = getChildAt(0); 22889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int top = view.getTop(); 22899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int height = view.getHeight(); 22909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (height > 0) { 22919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extent += (top * 100) / height; 22929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project view = getChildAt(count - 1); 22959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int bottom = view.getBottom(); 22969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project height = view.getHeight(); 22979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (height > 0) { 22989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project extent -= ((bottom - getHeight()) * 100) / height; 22999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return extent; 23029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 23049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 23079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int computeVerticalScrollOffset() { 23089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition >= 0 && getChildCount() > 0) { 23099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View view = getChildAt(0); 23109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int top = view.getTop(); 23119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int height = view.getHeight(); 23129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (height > 0) { 2313f2a204e792df5593cfe54efc95d04b7e764795c1Adam Powell final int numColumns = mNumColumns; 2314f2a204e792df5593cfe54efc95d04b7e764795c1Adam Powell final int rowCount = (mItemCount + numColumns - 1) / numColumns; 2315bbf7b4cdcfbc5aa436500dad96e73f7a3b32e794Pieter-Jan Vandormael // In case of stackFromBottom the calculation of whichRow needs 2316bbf7b4cdcfbc5aa436500dad96e73f7a3b32e794Pieter-Jan Vandormael // to take into account that counting from the top the first row 2317bbf7b4cdcfbc5aa436500dad96e73f7a3b32e794Pieter-Jan Vandormael // might not be entirely filled. 2318bbf7b4cdcfbc5aa436500dad96e73f7a3b32e794Pieter-Jan Vandormael final int oddItemsOnFirstRow = isStackFromBottom() ? ((rowCount * numColumns) - 2319bbf7b4cdcfbc5aa436500dad96e73f7a3b32e794Pieter-Jan Vandormael mItemCount) : 0; 2320bbf7b4cdcfbc5aa436500dad96e73f7a3b32e794Pieter-Jan Vandormael final int whichRow = (mFirstPosition + oddItemsOnFirstRow) / numColumns; 2321f2a204e792df5593cfe54efc95d04b7e764795c1Adam Powell return Math.max(whichRow * 100 - (top * 100) / height + 2322f2a204e792df5593cfe54efc95d04b7e764795c1Adam Powell (int) ((float) mScrollY / getHeight() * rowCount * 100), 0); 23239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 23269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 23299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected int computeVerticalScrollRange() { 23309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: Account for vertical spacing too 23319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numColumns = mNumColumns; 23329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int rowCount = (mItemCount + numColumns - 1) / numColumns; 2333637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell int result = Math.max(rowCount * 100, 0); 2334637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (mScrollY != 0) { 2335637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell // Compensate for overscroll 2336637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell result += Math.abs((int) ((float) mScrollY / getHeight() * rowCount * 100)); 2337637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 2338637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell return result; 23399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23418a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 2342a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn public CharSequence getAccessibilityClassName() { 2343a7bb6fbeab933326d58aa806d8194b7b13239d34Dianne Hackborn return GridView.class.getName(); 23448a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 23458a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 2346a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette /** @hide */ 23478a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 2348a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) { 2349a54956a0bc611b1e9b3914edc7a604b59688f6b7Alan Viverette super.onInitializeAccessibilityNodeInfoInternal(info); 23505b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette 23515b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette final int columnsCount = getNumColumns(); 23525b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette final int rowsCount = getCount() / columnsCount; 235376769ae02e713f50816ee67ff618b748d95050a8Alan Viverette final int selectionMode = getSelectionModeForAccessibility(); 235476769ae02e713f50816ee67ff618b748d95050a8Alan Viverette final CollectionInfo collectionInfo = CollectionInfo.obtain( 235577c180a5137348022fce388930a9781863f83e74Alan Viverette rowsCount, columnsCount, false, selectionMode); 23565b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette info.setCollectionInfo(collectionInfo); 235723f4432437b2ab742971055b7eb79b346894f24bAlan Viverette 235823f4432437b2ab742971055b7eb79b346894f24bAlan Viverette if (columnsCount > 0 || rowsCount > 0) { 235923f4432437b2ab742971055b7eb79b346894f24bAlan Viverette info.addAction(AccessibilityAction.ACTION_SCROLL_TO_POSITION); 236023f4432437b2ab742971055b7eb79b346894f24bAlan Viverette } 236123f4432437b2ab742971055b7eb79b346894f24bAlan Viverette } 236223f4432437b2ab742971055b7eb79b346894f24bAlan Viverette 236323f4432437b2ab742971055b7eb79b346894f24bAlan Viverette /** @hide */ 236423f4432437b2ab742971055b7eb79b346894f24bAlan Viverette @Override 236523f4432437b2ab742971055b7eb79b346894f24bAlan Viverette public boolean performAccessibilityActionInternal(int action, Bundle arguments) { 236623f4432437b2ab742971055b7eb79b346894f24bAlan Viverette if (super.performAccessibilityActionInternal(action, arguments)) { 236723f4432437b2ab742971055b7eb79b346894f24bAlan Viverette return true; 236823f4432437b2ab742971055b7eb79b346894f24bAlan Viverette } 236923f4432437b2ab742971055b7eb79b346894f24bAlan Viverette 237023f4432437b2ab742971055b7eb79b346894f24bAlan Viverette switch (action) { 237123f4432437b2ab742971055b7eb79b346894f24bAlan Viverette case R.id.accessibilityActionScrollToPosition: { 237223f4432437b2ab742971055b7eb79b346894f24bAlan Viverette // GridView only supports scrolling in one direction, so we can 237323f4432437b2ab742971055b7eb79b346894f24bAlan Viverette // ignore the column argument. 237423f4432437b2ab742971055b7eb79b346894f24bAlan Viverette final int numColumns = getNumColumns(); 237523f4432437b2ab742971055b7eb79b346894f24bAlan Viverette final int row = arguments.getInt(AccessibilityNodeInfo.ACTION_ARGUMENT_ROW_INT, -1); 237623f4432437b2ab742971055b7eb79b346894f24bAlan Viverette final int position = Math.min(row * numColumns, getCount() - 1); 237723f4432437b2ab742971055b7eb79b346894f24bAlan Viverette if (row >= 0) { 237823f4432437b2ab742971055b7eb79b346894f24bAlan Viverette // The accessibility service gets data asynchronously, so 237923f4432437b2ab742971055b7eb79b346894f24bAlan Viverette // we'll be a little lenient by clamping the last position. 238023f4432437b2ab742971055b7eb79b346894f24bAlan Viverette smoothScrollToPosition(position); 238123f4432437b2ab742971055b7eb79b346894f24bAlan Viverette return true; 238223f4432437b2ab742971055b7eb79b346894f24bAlan Viverette } 238323f4432437b2ab742971055b7eb79b346894f24bAlan Viverette } break; 238423f4432437b2ab742971055b7eb79b346894f24bAlan Viverette } 238523f4432437b2ab742971055b7eb79b346894f24bAlan Viverette 238623f4432437b2ab742971055b7eb79b346894f24bAlan Viverette return false; 23875b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette } 23885b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette 23895b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette @Override 23905b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette public void onInitializeAccessibilityNodeInfoForItem( 23915b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette View view, int position, AccessibilityNodeInfo info) { 23925b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette super.onInitializeAccessibilityNodeInfoForItem(view, position, info); 23935b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette 23945b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette final int count = getCount(); 23955b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette final int columnsCount = getNumColumns(); 23965b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette final int rowsCount = count / columnsCount; 23975b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette 23985b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette final int row; 23995b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette final int column; 24005b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette if (!mStackFromBottom) { 24015b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette column = position % columnsCount; 24025b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette row = position / columnsCount; 24035b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette } else { 24045b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette final int invertedIndex = count - 1 - position; 24055b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette 24065b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette column = columnsCount - 1 - (invertedIndex % columnsCount); 24075b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette row = rowsCount - 1 - invertedIndex / columnsCount; 24085b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette } 24095b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette 24105b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette final LayoutParams lp = (LayoutParams) view.getLayoutParams(); 2411061b16ff88ede08b0333d2bad5f1f9b60a302183Steven Dao final boolean isHeading = lp != null && lp.viewType == ITEM_VIEW_TYPE_HEADER_OR_FOOTER; 241276769ae02e713f50816ee67ff618b748d95050a8Alan Viverette final boolean isSelected = isItemChecked(position); 241376769ae02e713f50816ee67ff618b748d95050a8Alan Viverette final CollectionItemInfo itemInfo = CollectionItemInfo.obtain( 241477c180a5137348022fce388930a9781863f83e74Alan Viverette row, 1, column, 1, isHeading, isSelected); 24155b2081dc41cccd76780a2cb4e9a973505c13446cAlan Viverette info.setCollectionItemInfo(itemInfo); 24168a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 241794a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy 241894a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy /** @hide */ 241994a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy @Override 242094a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy protected void encodeProperties(@NonNull ViewHierarchyEncoder encoder) { 242194a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy super.encodeProperties(encoder); 242294a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy encoder.addProperty("numColumns", getNumColumns()); 242394a6d15ede149189bba9e5f474ed853c98230e75Siva Velusamy } 24248a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov} 2425