ListView.java revision 2a93911b87f7aac6d0dcceabc5983e81befeeda5
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 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 19fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunneimport com.android.internal.R; 204e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brownimport com.android.internal.util.Predicate; 21fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunneimport com.google.android.collect.Lists; 22fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunne 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 24499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.content.Intent; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 278f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guyimport android.graphics.Paint; 28fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunneimport android.graphics.PixelFormat; 29fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunneimport android.graphics.Rect; 30fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunneimport android.graphics.drawable.Drawable; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 3230ee76cf05f785bbf819b71954242c835c597ce1alanvimport android.util.MathUtils; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.SparseBooleanArray; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.FocusFinder; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.KeyEvent; 36fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunneimport android.view.SoundEffectConstants; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewDebug; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewGroup; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewParent; 4127093def8d5b13982b5dd4d949909ecdf7ec2fd6alanvimport android.view.ViewRootImpl; 4275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.view.accessibility.AccessibilityEvent; 438a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 44499cb9f516062b654952d282f211bee44c31a3c2Winson Chungimport android.widget.RemoteViews.RemoteView; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Implementation Notes: 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Some terminology: 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * index - index of the items that are currently visible 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * position - index of the items in the cursor 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A view that shows items in a vertically scrolling list. The items 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * come from the {@link ListAdapter} associated with this view. 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 624c359b76f9a030f92a302ba74a528faa170bad4eScott Main * <p>See the <a href="{@docRoot}guide/topics/ui/layout/listview.html">List View</a> 634c359b76f9a030f92a302ba74a528faa170bad4eScott Main * guide.</p> 6441ec65355bd6ded652769725b276d47c54a0d913Scott Main * 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ListView_entries 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ListView_divider 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ListView_dividerHeight 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ListView_headerDividersEnabled 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ListView_footerDividersEnabled 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 71499cb9f516062b654952d282f211bee44c31a3c2Winson Chung@RemoteView 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ListView extends AbsListView { 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Used to indicate a no preference for a position type. 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int NO_POSITION = -1; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When arrow scrolling, ListView will never scroll more than this factor 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * times the height of the list. 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final float MAX_SCROLL_FACTOR = 0.33f; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When arrow scrolling, need a certain amount of pixels to preview next 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * items. This is usually the fading edge, but if that is small enough, 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * we want to make sure we preview at least this many pixels. 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int MIN_SCROLL_PREVIEW_PIXELS = 2; 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A class that represents a fixed view in a list, for example a header at the top 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or a footer at the bottom. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public class FixedViewInfo { 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The view to add to the list */ 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public View view; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The data backing the view. This is returned from {@link ListAdapter#getItem(int)}. */ 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Object data; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** <code>true</code> if the fixed view should be selectable in the list */ 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isSelectable; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<FixedViewInfo> mHeaderViewInfos = Lists.newArrayList(); 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrayList<FixedViewInfo> mFooterViewInfos = Lists.newArrayList(); 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Drawable mDivider; 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int mDividerHeight; 109fb60386b46d0c6216c765c10bd33ac42ca780917Adam Cohen 110637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell Drawable mOverScrollHeader; 111637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell Drawable mOverScrollFooter; 112637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 11324443ea3992e372e47daa50266b0f2ec38cac388Romain Guy private boolean mIsCacheColorOpaque; 11424443ea3992e372e47daa50266b0f2ec38cac388Romain Guy private boolean mDividerIsOpaque; 11524443ea3992e372e47daa50266b0f2ec38cac388Romain Guy 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mHeaderDividersEnabled; 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mFooterDividersEnabled; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mAreAllItemsSelectable = true; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mItemsCanFocus = false; 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // used for temporary calculations. 124c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project private final Rect mTempRect = new Rect(); 125a02903fbee6725563da4472bd120f844e9d5518cRomain Guy private Paint mDividerPaint; 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the single allocated result per list view; kinda cheesey but avoids 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // allocating these thingies too often. 1299c3184cc162ee8c10eabd3f996629a9397a1f551Romain Guy private final ArrowScrollFocusResult mArrowScrollFocusResult = new ArrowScrollFocusResult(); 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell // Keeps focused children visible through resizes 1329bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell private FocusSelector mFocusSelector; 1338350f7dbc3a62211b2891f35911e4073d24c4cc5Adam Powell 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ListView(Context context) { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, null); 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ListView(Context context, AttributeSet attrs) { 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, attrs, com.android.internal.R.attr.listViewStyle); 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ListView(Context context, AttributeSet attrs, int defStyle) { 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context, attrs, defStyle); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedArray a = context.obtainStyledAttributes(attrs, 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.ListView, defStyle, 0); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project CharSequence[] entries = a.getTextArray( 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.ListView_entries); 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (entries != null) { 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setAdapter(new ArrayAdapter<CharSequence>(context, 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.layout.simple_list_item_1, entries)); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Drawable d = a.getDrawable(com.android.internal.R.styleable.ListView_divider); 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (d != null) { 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If a divider is specified use its intrinsic height for divider height 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setDivider(d); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 160bfb5d4b93bb739a012ecec604473838c1343c88aAdam Powell 161637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final Drawable osHeader = a.getDrawable( 162637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell com.android.internal.R.styleable.ListView_overScrollHeader); 163637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (osHeader != null) { 164637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell setOverscrollHeader(osHeader); 165637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 166637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 167637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final Drawable osFooter = a.getDrawable( 168637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell com.android.internal.R.styleable.ListView_overScrollFooter); 169637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (osFooter != null) { 170637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell setOverscrollFooter(osFooter); 171637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 172637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Use the height specified, zero being the default 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int dividerHeight = a.getDimensionPixelSize( 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.ListView_dividerHeight, 0); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dividerHeight != 0) { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setDividerHeight(dividerHeight); 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderDividersEnabled = a.getBoolean(R.styleable.ListView_headerDividersEnabled, true); 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFooterDividersEnabled = a.getBoolean(R.styleable.ListView_footerDividersEnabled, true); 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The maximum amount a list view will scroll in response to 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * an arrow event. 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getMaxScrollAmount() { 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (int) (MAX_SCROLL_FACTOR * (mBottom - mTop)); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Make sure views are touching the top or bottom edge, as appropriate for 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * our gravity 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void adjustViewsUpOrDown() { 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childCount = getChildCount(); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int delta; 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childCount > 0) { 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child; 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Uh-oh -- we came up short. Slide all views up to make them 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // align with the top 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child = getChildAt(0); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta = child.getTop() - mListPadding.top; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition != 0) { 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It's OK to have some space above the first item if it is 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // part of the vertical spacing 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta -= mDividerHeight; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (delta < 0) { 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We only are looking to see if we are too low, not too high 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta = 0; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we are too high, slide all views down to align with bottom 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child = getChildAt(childCount - 1); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta = child.getBottom() - (getHeight() - mListPadding.bottom); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition + childCount < mItemCount) { 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It's OK to have some space below the last item if it is 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // part of the vertical spacing 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta += mDividerHeight; 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (delta > 0) { 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta = 0; 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (delta != 0) { 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(-delta); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Add a fixed view to appear at the top of the list. If addHeaderView is 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * called more than once, the views will appear in the order they were 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * added. Views added using this call can take focus if they want. 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * NOTE: Call this before calling setAdapter. This is so ListView can wrap 247176f9fc215194411cf0461a178d77fa57486112bGilles Debunne * the supplied cursor with one that will also account for header and footer 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * views. 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param v The view to add. 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param data Data to associate with this view 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param isSelectable whether the item is selectable 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addHeaderView(View v, Object data, boolean isSelectable) { 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25622c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen if (mAdapter != null && ! (mAdapter instanceof HeaderViewListAdapter)) { 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException( 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "Cannot add header view to list -- setAdapter has already been called."); 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FixedViewInfo info = new FixedViewInfo(); 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project info.view = v; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project info.data = data; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project info.isSelectable = isSelectable; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderViewInfos.add(info); 26622c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen 26722c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen // in the case of re-adding a header view, or adding one later on, 26822c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen // we need to notify the observer 269247a0f0a16f956c463644f732dacb6c8d0979ba3Adam Powell if (mAdapter != null && mDataSetObserver != null) { 27022c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen mDataSetObserver.onChanged(); 27122c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Add a fixed view to appear at the top of the list. If addHeaderView is 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * called more than once, the views will appear in the order they were 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * added. Views added using this call can take focus if they want. 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * NOTE: Call this before calling setAdapter. This is so ListView can wrap 280176f9fc215194411cf0461a178d77fa57486112bGilles Debunne * the supplied cursor with one that will also account for header and footer 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * views. 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param v The view to add. 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addHeaderView(View v) { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addHeaderView(v, null, true); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getHeaderViewsCount() { 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mHeaderViewInfos.size(); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Removes a previously-added header view. 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param v The view to remove 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return true if the view was removed, false if the view was not a header 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * view 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean removeHeaderView(View v) { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mHeaderViewInfos.size() > 0) { 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean result = false; 304247a0f0a16f956c463644f732dacb6c8d0979ba3Adam Powell if (mAdapter != null && ((HeaderViewListAdapter) mAdapter).removeHeader(v)) { 30522c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen if (mDataSetObserver != null) { 30622c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen mDataSetObserver.onChanged(); 30722c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen } 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = true; 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeFixedViewInfo(v, mHeaderViewInfos); 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void removeFixedViewInfo(View v, ArrayList<FixedViewInfo> where) { 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = where.size(); 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < len; ++i) { 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FixedViewInfo info = where.get(i); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (info.view == v) { 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project where.remove(i); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Add a fixed view to appear at the bottom of the list. If addFooterView is 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * called more than once, the views will appear in the order they were 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * added. Views added using this call can take focus if they want. 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * NOTE: Call this before calling setAdapter. This is so ListView can wrap 333176f9fc215194411cf0461a178d77fa57486112bGilles Debunne * the supplied cursor with one that will also account for header and footer 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * views. 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param v The view to add. 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param data Data to associate with this view 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param isSelectable true if the footer view can be selected 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addFooterView(View v, Object data, boolean isSelectable) { 34122c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen 34263f9689627b8fd9b94afd35b1274939c56e5642fMarco Nelissen // NOTE: do not enforce the adapter being null here, since unlike in 34363f9689627b8fd9b94afd35b1274939c56e5642fMarco Nelissen // addHeaderView, it was never enforced here, and so existing apps are 34463f9689627b8fd9b94afd35b1274939c56e5642fMarco Nelissen // relying on being able to add a footer and then calling setAdapter to 34563f9689627b8fd9b94afd35b1274939c56e5642fMarco Nelissen // force creation of the HeaderViewListAdapter wrapper 34622c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project FixedViewInfo info = new FixedViewInfo(); 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project info.view = v; 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project info.data = data; 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project info.isSelectable = isSelectable; 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFooterViewInfos.add(info); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // in the case of re-adding a footer view, or adding one later on, 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we need to notify the observer 355247a0f0a16f956c463644f732dacb6c8d0979ba3Adam Powell if (mAdapter != null && mDataSetObserver != null) { 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataSetObserver.onChanged(); 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Add a fixed view to appear at the bottom of the list. If addFooterView is called more 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * than once, the views will appear in the order they were added. Views added using 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this call can take focus if they want. 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>NOTE: Call this before calling setAdapter. This is so ListView can wrap the supplied 365176f9fc215194411cf0461a178d77fa57486112bGilles Debunne * cursor with one that will also account for header and footer views. 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param v The view to add. 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addFooterView(View v) { 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addFooterView(v, null, true); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getFooterViewsCount() { 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mFooterViewInfos.size(); 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Removes a previously-added footer view. 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param v The view to remove 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * true if the view was removed, false if the view was not a footer view 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean removeFooterView(View v) { 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFooterViewInfos.size() > 0) { 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean result = false; 389247a0f0a16f956c463644f732dacb6c8d0979ba3Adam Powell if (mAdapter != null && ((HeaderViewListAdapter) mAdapter).removeFooter(v)) { 39022c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen if (mDataSetObserver != null) { 39122c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen mDataSetObserver.onChanged(); 39222c04a316a482176957fd27285c0fe36e2f3979cMarco Nelissen } 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project result = true; 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeFixedViewInfo(v, mFooterViewInfos); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return result; 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the adapter currently in use in this ListView. The returned adapter 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * might not be the same adapter passed to {@link #setAdapter(ListAdapter)} but 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * might be a {@link WrapperListAdapter}. 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The adapter currently used to display data in this ListView. 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setAdapter(ListAdapter) 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ListAdapter getAdapter() { 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 416499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * Sets up this AbsListView to use a remote views adapter which connects to a RemoteViewsService 417499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * through the specified intent. 418499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * @param intent the intent used to identify the RemoteViewsService for the adapter to connect to. 419499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 420499cb9f516062b654952d282f211bee44c31a3c2Winson Chung @android.view.RemotableViewMethod 421499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public void setRemoteViewsAdapter(Intent intent) { 422499cb9f516062b654952d282f211bee44c31a3c2Winson Chung super.setRemoteViewsAdapter(intent); 423499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 424499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 425499cb9f516062b654952d282f211bee44c31a3c2Winson Chung /** 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the data behind this ListView. 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The adapter passed to this method may be wrapped by a {@link WrapperListAdapter}, 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * depending on the ListView features currently in use. For instance, adding 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * headers and/or footers will cause the adapter to be wrapped. 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param adapter The ListAdapter which is responsible for maintaining the 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * data backing this list and for producing a view to represent an 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * item in that data set. 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #getAdapter() 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAdapter(ListAdapter adapter) { 440df36b0579e1e550de3d66a20362717e49b23235cRomain Guy if (mAdapter != null && mDataSetObserver != null) { 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAdapter.unregisterDataSetObserver(mDataSetObserver); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetList(); 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRecycler.clear(); 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) { 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter); 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAdapter = adapter; 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOldSelectedPosition = INVALID_POSITION; 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOldSelectedRowId = INVALID_ROW_ID; 455f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell 456f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell // AbsListView#setAdapter will update choice mode states. 457f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell super.setAdapter(adapter); 458f343e1ba7e796120eefa917dbf78348feea98e11Adam Powell 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAdapter != null) { 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAreAllItemsSelectable = mAdapter.areAllItemsEnabled(); 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOldItemCount = mItemCount; 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mItemCount = mAdapter.getCount(); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkFocus(); 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataSetObserver = new AdapterDataSetObserver(); 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAdapter.registerDataSetObserver(mDataSetObserver); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRecycler.setViewTypeCount(mAdapter.getViewTypeCount()); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int position; 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStackFromBottom) { 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position = lookForSelectablePosition(mItemCount - 1, false); 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position = lookForSelectablePosition(0, true); 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectedPositionInt(position); 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setNextSelectedPositionInt(position); 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mItemCount == 0) { 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Nothing selected 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkSelectionChanged(); 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAreAllItemsSelectable = true; 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkFocus(); 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Nothing selected 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkSelectionChanged(); 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(); 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The list is empty. Clear everything out. 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void resetList() { 4992e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy // The parent's resetList() will remove all views from the layout so we need to 5002e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy // cleanup the state of our footers and headers 5012e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy clearRecycledState(mHeaderViewInfos); 5022e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy clearRecycledState(mFooterViewInfos); 5032e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.resetList(); 5052e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_NORMAL; 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5092e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy private void clearRecycledState(ArrayList<FixedViewInfo> infos) { 5102e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy if (infos != null) { 5112e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy final int count = infos.size(); 5122e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy 5132e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy for (int i = 0; i < count; i++) { 5142e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy final View child = infos.get(i).view; 5152e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy final LayoutParams p = (LayoutParams) child.getLayoutParams(); 5162e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy if (p != null) { 5172e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy p.recycledHeaderFooter = false; 5182e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy } 5192e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy } 5202e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy } 5212e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy } 5222e447d46d9936c325fe5209262564fc3c5e795a2Romain Guy 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether the list needs to show the top fading edge 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean showingTopFadingEdge() { 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int listTop = mScrollY + mListPadding.top; 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (mFirstPosition > 0) || (getChildAt(0).getTop() > listTop); 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether the list needs to show the bottom fading edge 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean showingBottomFadingEdge() { 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childCount = getChildCount(); 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int bottomOfBottomChild = getChildAt(childCount - 1).getBottom(); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int lastVisiblePosition = mFirstPosition + childCount - 1; 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int listBottom = mScrollY + getHeight() - mListPadding.bottom; 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (lastVisiblePosition < mItemCount - 1) 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || (bottomOfBottomChild < listBottom); 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) { 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rectTopWithinChild = rect.top; 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // offset so rect is in coordinates of the this view 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rect.offset(child.getLeft(), child.getTop()); 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project rect.offset(-child.getScrollX(), -child.getScrollY()); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int height = getHeight(); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int listUnfadedTop = getScrollY(); 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int listUnfadedBottom = listUnfadedTop + height; 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int fadingEdge = getVerticalFadingEdgeLength(); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (showingTopFadingEdge()) { 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // leave room for top fading edge as long as rect isn't at very top 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mSelectedPosition > 0) || (rectTopWithinChild > fadingEdge)) { 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project listUnfadedTop += fadingEdge; 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childCount = getChildCount(); 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int bottomOfBottomChild = getChildAt(childCount - 1).getBottom(); 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (showingBottomFadingEdge()) { 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // leave room for bottom fading edge as long as rect isn't at very bottom 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mSelectedPosition < mItemCount - 1) 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || (rect.bottom < (bottomOfBottomChild - fadingEdge))) { 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project listUnfadedBottom -= fadingEdge; 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int scrollYDelta = 0; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rect.bottom > listUnfadedBottom && rect.top > listUnfadedTop) { 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // need to MOVE DOWN to get it in view: move down just enough so 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // that the entire rectangle is in view (or at least the first 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // screen size chunk). 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rect.height() > height) { 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // just enough to get screen size chunk on 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollYDelta += (rect.top - listUnfadedTop); 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // get entire rect at bottom of screen 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollYDelta += (rect.bottom - listUnfadedBottom); 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure we aren't scrolling beyond the end of our children 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int distanceToBottom = bottomOfBottomChild - listUnfadedBottom; 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollYDelta = Math.min(scrollYDelta, distanceToBottom); 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (rect.top < listUnfadedTop && rect.bottom < listUnfadedBottom) { 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // need to MOVE UP to get it in view: move up just enough so that 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // entire rectangle is in view (or at least the first screen 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // size chunk of it). 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rect.height() > height) { 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // screen size chunk 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollYDelta -= (listUnfadedBottom - rect.bottom); 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // entire rect at top 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollYDelta -= (listUnfadedTop - rect.top); 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // make sure we aren't scrolling any further than the top our children 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int top = getChildAt(0).getTop(); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int deltaToTop = top - listUnfadedTop; 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollYDelta = Math.max(scrollYDelta, deltaToTop); 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean scroll = scrollYDelta != 0; 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (scroll) { 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollListItemsBy(-scrollYDelta); 618079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn positionSelector(INVALID_POSITION, child); 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSelectedTop = child.getTop(); 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return scroll; 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@inheritDoc} 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void fillGap(boolean down) { 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = getChildCount(); 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (down) { 6328c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell int paddingTop = 0; 6338c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) { 6348c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell paddingTop = getListPaddingTop(); 6358c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell } 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int startOffset = count > 0 ? getChildAt(count - 1).getBottom() + mDividerHeight : 6378c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell paddingTop; 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(mFirstPosition + count, startOffset); 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooHigh(getChildCount()); 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6418c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell int paddingBottom = 0; 6428c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) { 6438c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell paddingBottom = getListPaddingBottom(); 6448c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell } 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int startOffset = count > 0 ? getChildAt(0).getTop() - mDividerHeight : 6468c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell getHeight() - paddingBottom; 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(mFirstPosition - 1, startOffset); 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooLow(getChildCount()); 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 * Fills the list from pos down to the end of the list view. 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param pos The first position to put in the list 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nextTop The location where the top of the item associated with pos 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * should be drawn 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that is currently selected, if it happens to be in the 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * range that we draw. 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillDown(int pos, int nextTop) { 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View selectedView = null; 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6668c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell int end = (mBottom - mTop); 6678c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) { 6688c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell end -= mListPadding.bottom; 6698c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell } 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (nextTop < end && pos < mItemCount) { 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // is this the selected item? 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean selected = pos == mSelectedPosition; 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child = makeAndAddView(pos, nextTop, true, mListPadding.left, selected); 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextTop = child.getBottom() + mDividerHeight; 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selected) { 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedView = child; 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos++; 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 683b967392e0170af8cfd8053fd43fcdf8c46f703e9Adam Cohen setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1); 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return selectedView; 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fills the list from pos up to the top of the list view. 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param pos The first position to put in the list 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nextBottom The location where the bottom of the item associated 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with pos should be drawn 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that is currently selected 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillUp(int pos, int nextBottom) { 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View selectedView = null; 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7008c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell int end = 0; 7018c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) { 7028c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell end = mListPadding.top; 7038c3e0fc84f69e9fe704dc20dd6c2bab1ce43fe93Adam Powell } 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (nextBottom > end && pos >= 0) { 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // is this the selected item? 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean selected = pos == mSelectedPosition; 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child = makeAndAddView(pos, nextBottom, false, mListPadding.left, selected); 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextBottom = child.getTop() - mDividerHeight; 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selected) { 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedView = child; 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos--; 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = pos + 1; 717b967392e0170af8cfd8053fd43fcdf8c46f703e9Adam Cohen setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1); 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return selectedView; 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fills the list from top to bottom, starting with mFirstPosition 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nextTop The location where the top of the first item should be 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * drawn 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that is currently selected 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillFromTop(int nextTop) { 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = Math.min(mFirstPosition, mSelectedPosition); 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = Math.min(mFirstPosition, mItemCount - 1); 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition < 0) { 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = 0; 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return fillDown(mFirstPosition, nextTop); 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Put mSelectedPosition in the middle of the screen and then build up and 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * down from there. This method forces mSelectedPosition to the center. 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenTop Top of the area in which children can be drawn, as 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * measured in pixels 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenBottom Bottom of the area in which children can be drawn, 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * as measured in pixels 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Currently selected view 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillFromMiddle(int childrenTop, int childrenBottom) { 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int height = childrenBottom - childrenTop; 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int position = reconcileSelectedPosition(); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View sel = makeAndAddView(position, childrenTop, true, 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListPadding.left, true); 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = position; 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int selHeight = sel.getMeasuredHeight(); 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selHeight <= height) { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel.offsetTopAndBottom((height - selHeight) / 2); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillAboveAndBelow(sel, position); 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooHigh(getChildCount()); 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooLow(getChildCount()); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sel; 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Once the selected view as been placed, fill up the visible area above and 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * below it. 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param sel The selected view 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position The position corresponding to sel 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void fillAboveAndBelow(View sel, int position) { 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int dividerHeight = mDividerHeight; 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(position - 1, sel.getTop() - dividerHeight); 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(position + 1, sel.getBottom() + dividerHeight); 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(position + 1, sel.getBottom() + dividerHeight); 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(position - 1, sel.getTop() - dividerHeight); 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fills the grid based on positioning the new selection at a specific 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * location. The selection may be moved so that it does not intersect the 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * faded edges. The grid is then filled upwards and downwards from there. 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectedTop Where the selected item should be 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenTop Where to start drawing children 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenBottom Last pixel where children can be drawn 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that currently has selection 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillFromSelection(int selectedTop, int childrenTop, int childrenBottom) { 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fadingEdgeLength = getVerticalFadingEdgeLength(); 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int selectedPosition = mSelectedPosition; 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View sel; 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength, 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedPosition); 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int bottomSelectionPixel = getBottomSelectionPixel(childrenBottom, fadingEdgeLength, 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedPosition); 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = makeAndAddView(selectedPosition, selectedTop, true, mListPadding.left, true); 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Some of the newly selected item extends below the bottom of the list 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sel.getBottom() > bottomSelectionPixel) { 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space available above the selection into which we can scroll 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // upwards 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int spaceAbove = sel.getTop() - topSelectionPixel; 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space required to bring the bottom of the selected item 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // fully into view 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int spaceBelow = sel.getBottom() - bottomSelectionPixel; 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int offset = Math.min(spaceAbove, spaceBelow); 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Now offset the selected item to get it into view 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel.offsetTopAndBottom(-offset); 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (sel.getTop() < topSelectionPixel) { 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space required to bring the top of the selected item fully 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // into view 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int spaceAbove = topSelectionPixel - sel.getTop(); 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space available below the selection into which we can scroll 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // downwards 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int spaceBelow = bottomSelectionPixel - sel.getBottom(); 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int offset = Math.min(spaceAbove, spaceBelow); 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Offset the selected item to get it into view 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel.offsetTopAndBottom(offset); 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fill in views above and below 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillAboveAndBelow(sel, selectedPosition); 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooHigh(getChildCount()); 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooLow(getChildCount()); 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sel; 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Calculate the bottom-most pixel we can draw the selection into 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenBottom Bottom pixel were children can be drawn 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param fadingEdgeLength Length of the fading edge in pixels, if present 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectedPosition The position that will be selected 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The bottom-most pixel we can draw the selection into 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getBottomSelectionPixel(int childrenBottom, int fadingEdgeLength, 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int selectedPosition) { 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int bottomSelectionPixel = childrenBottom; 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selectedPosition != mItemCount - 1) { 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottomSelectionPixel -= fadingEdgeLength; 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return bottomSelectionPixel; 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Calculate the top-most pixel we can draw the selection into 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenTop Top pixel were children can be drawn 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param fadingEdgeLength Length of the fading edge in pixels, if present 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectedPosition The position that will be selected 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The top-most pixel we can draw the selection into 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getTopSelectionPixel(int childrenTop, int fadingEdgeLength, int selectedPosition) { 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // first pixel we can draw the selection into 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int topSelectionPixel = childrenTop; 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selectedPosition > 0) { 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project topSelectionPixel += fadingEdgeLength; 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return topSelectionPixel; 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 892499cb9f516062b654952d282f211bee44c31a3c2Winson Chung /** 893499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * Smoothly scroll to the specified adapter position. The view will 894499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * scroll such that the indicated position is displayed. 895499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * @param position Scroll to this adapter position. 896499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 897499cb9f516062b654952d282f211bee44c31a3c2Winson Chung @android.view.RemotableViewMethod 898499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public void smoothScrollToPosition(int position) { 899499cb9f516062b654952d282f211bee44c31a3c2Winson Chung super.smoothScrollToPosition(position); 900499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 901499cb9f516062b654952d282f211bee44c31a3c2Winson Chung 902499cb9f516062b654952d282f211bee44c31a3c2Winson Chung /** 903499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * Smoothly scroll to the specified adapter position offset. The view will 904499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * scroll such that the indicated position is displayed. 905499cb9f516062b654952d282f211bee44c31a3c2Winson Chung * @param offset The amount to offset from the adapter position to scroll to. 906499cb9f516062b654952d282f211bee44c31a3c2Winson Chung */ 907499cb9f516062b654952d282f211bee44c31a3c2Winson Chung @android.view.RemotableViewMethod 908499cb9f516062b654952d282f211bee44c31a3c2Winson Chung public void smoothScrollByOffset(int offset) { 909499cb9f516062b654952d282f211bee44c31a3c2Winson Chung super.smoothScrollByOffset(offset); 910499cb9f516062b654952d282f211bee44c31a3c2Winson Chung } 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Fills the list based on positioning the new selection relative to the old 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selection. The new selection will be placed at, above, or below the 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * location of the new selection depending on how the selection is moving. 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The selection will then be pinned to the visible part of the screen, 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * excluding the edges that are faded. The list is then filled upwards and 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * downwards from there. 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param oldSel The old selected view. Useful for trying to put the new 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selection in the same place 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param newSel The view that is to become selected. Useful for trying to 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * put the new selection in the same place 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param delta Which way we are moving 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenTop Where to start drawing children 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenBottom Last pixel where children can be drawn 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The view that currently has selection 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View moveSelection(View oldSel, View newSel, int delta, int childrenTop, 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childrenBottom) { 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fadingEdgeLength = getVerticalFadingEdgeLength(); 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int selectedPosition = mSelectedPosition; 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View sel; 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int topSelectionPixel = getTopSelectionPixel(childrenTop, fadingEdgeLength, 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedPosition); 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int bottomSelectionPixel = getBottomSelectionPixel(childrenTop, fadingEdgeLength, 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedPosition); 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (delta > 0) { 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Case 1: Scrolling down. 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Before After 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * | | | | 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * +-------+ +-------+ 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * | A | | A | 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * | 1 | => +-------+ 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * +-------+ | B | 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * | B | | 2 | 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * +-------+ +-------+ 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * | | | | 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Try to keep the top of the previously selected item where it was. 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * oldSel = A 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * sel = B 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Put oldSel (A) where it belongs 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldSel = makeAndAddView(selectedPosition - 1, oldSel.getTop(), true, 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListPadding.left, false); 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int dividerHeight = mDividerHeight; 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Now put the new selection (B) below that 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = makeAndAddView(selectedPosition, oldSel.getBottom() + dividerHeight, true, 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListPadding.left, true); 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Some of the newly selected item extends below the bottom of the list 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sel.getBottom() > bottomSelectionPixel) { 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space available above the selection into which we can scroll upwards 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spaceAbove = sel.getTop() - topSelectionPixel; 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space required to bring the bottom of the selected item fully into view 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spaceBelow = sel.getBottom() - bottomSelectionPixel; 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't scroll more than half the height of the list 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int halfVerticalSpace = (childrenBottom - childrenTop) / 2; 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int offset = Math.min(spaceAbove, spaceBelow); 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offset = Math.min(offset, halfVerticalSpace); 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We placed oldSel, so offset that item 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldSel.offsetTopAndBottom(-offset); 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Now offset the selected item to get it into view 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel.offsetTopAndBottom(-offset); 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fill in views above and below 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(mSelectedPosition - 2, sel.getTop() - dividerHeight); 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(mSelectedPosition + 1, sel.getBottom() + dividerHeight); 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillDown(mSelectedPosition + 1, sel.getBottom() + dividerHeight); 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(mSelectedPosition - 2, sel.getTop() - dividerHeight); 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (delta < 0) { 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Case 2: Scrolling up. 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Before After 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * | | | | 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * +-------+ +-------+ 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * | A | | A | 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * +-------+ => | 1 | 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * | B | +-------+ 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * | 2 | | B | 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * +-------+ +-------+ 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * | | | | 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Try to keep the top of the item about to become selected where it was. 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * newSel = A 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * olSel = B 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newSel != null) { 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Try to position the top of newSel (A) where it was before it was selected 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = makeAndAddView(selectedPosition, newSel.getTop(), true, mListPadding.left, 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project true); 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If (A) was not on screen and so did not have a view, position 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // it above the oldSel (B) 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = makeAndAddView(selectedPosition, oldSel.getTop(), false, mListPadding.left, 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project true); 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Some of the newly selected item extends above the top of the list 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sel.getTop() < topSelectionPixel) { 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space required to bring the top of the selected item fully into view 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spaceAbove = topSelectionPixel - sel.getTop(); 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Find space available below the selection into which we can scroll downwards 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int spaceBelow = bottomSelectionPixel - sel.getBottom(); 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't scroll more than half the height of the list 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int halfVerticalSpace = (childrenBottom - childrenTop) / 2; 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int offset = Math.min(spaceAbove, spaceBelow); 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offset = Math.min(offset, halfVerticalSpace); 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Offset the selected item to get it into view 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel.offsetTopAndBottom(offset); 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fill in views above and below 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillAboveAndBelow(sel, selectedPosition); 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oldTop = oldSel.getTop(); 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Case 3: Staying still 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = makeAndAddView(selectedPosition, oldTop, true, mListPadding.left, true); 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We're staying still... 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (oldTop < childrenTop) { 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ... but the top of the old selection was off screen. 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (This can happen if the data changes size out from under us) 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newBottom = sel.getBottom(); 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newBottom < childrenTop + 20) { 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Not enough visible -- bring it onscreen 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel.offsetTopAndBottom(childrenTop - sel.getTop()); 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fill in views above and below 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillAboveAndBelow(sel, selectedPosition); 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sel; 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10809bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell private class FocusSelector implements Runnable { 10819bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell private int mPosition; 10829bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell private int mPositionTop; 10839bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell 10849bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell public FocusSelector setup(int position, int top) { 10859bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell mPosition = position; 10869bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell mPositionTop = top; 10879bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell return this; 10889bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell } 10899bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell 10909bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell public void run() { 10919bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell setSelectionFromTop(mPosition, mPositionTop); 10929bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell } 10939bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell } 10949bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell 10959bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell @Override 10969bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell protected void onSizeChanged(int w, int h, int oldw, int oldh) { 10979bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell if (getChildCount() > 0) { 10989bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell View focusedChild = getFocusedChild(); 10999bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell if (focusedChild != null) { 11009bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell final int childPosition = mFirstPosition + indexOfChild(focusedChild); 11019bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell final int childBottom = focusedChild.getBottom(); 11029bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell final int offset = Math.max(0, childBottom - (h - mPaddingTop)); 11039bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell final int top = focusedChild.getTop() - offset; 11049bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell if (mFocusSelector == null) { 11059bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell mFocusSelector = new FocusSelector(); 11069bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell } 11079bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell post(mFocusSelector.setup(childPosition, top)); 11089bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell } 11099bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell } 11109bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell super.onSizeChanged(w, h, oldw, oldh); 11119bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell } 11129bf3c128509de5bd66222943a00acfcd1000cd62Adam Powell 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Sets up mListPadding 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onMeasure(widthMeasureSpec, heightMeasureSpec); 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int widthMode = MeasureSpec.getMode(widthMeasureSpec); 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int heightMode = MeasureSpec.getMode(heightMeasureSpec); 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int widthSize = MeasureSpec.getSize(widthMeasureSpec); 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int heightSize = MeasureSpec.getSize(heightMeasureSpec); 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childWidth = 0; 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childHeight = 0; 1125189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn int childState = 0; 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mItemCount = mAdapter == null ? 0 : mAdapter.getCount(); 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mItemCount > 0 && (widthMode == MeasureSpec.UNSPECIFIED || 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project heightMode == MeasureSpec.UNSPECIFIED)) { 113021875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy final View child = obtainView(0, mIsScrap); 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project measureScrapChild(child, 0, widthMeasureSpec); 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childWidth = child.getMeasuredWidth(); 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childHeight = child.getMeasuredHeight(); 1136189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn childState = combineMeasuredStates(childState, child.getMeasuredState()); 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11389c3184cc162ee8c10eabd3f996629a9397a1f551Romain Guy if (recycleOnMeasure() && mRecycler.shouldRecycleViewType( 11399c3184cc162ee8c10eabd3f996629a9397a1f551Romain Guy ((LayoutParams) child.getLayoutParams()).viewType)) { 1140079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn mRecycler.addScrapView(child, -1); 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (widthMode == MeasureSpec.UNSPECIFIED) { 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widthSize = mListPadding.left + mListPadding.right + childWidth + 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getVerticalScrollbarWidth(); 1147189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn } else { 1148189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn widthSize |= (childState&MEASURED_STATE_MASK); 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (heightMode == MeasureSpec.UNSPECIFIED) { 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project heightSize = mListPadding.top + mListPadding.bottom + childHeight + 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getVerticalFadingEdgeLength() * 2; 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (heightMode == MeasureSpec.AT_MOST) { 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: after first layout we should maybe start at the first visible position, not 0 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project heightSize = measureHeightOfChildren(widthMeasureSpec, 0, NO_POSITION, heightSize, -1); 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1161189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn setMeasuredDimension(widthSize , heightSize); 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWidthMeasureSpec = widthMeasureSpec; 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void measureScrapChild(View child, int position, int widthMeasureSpec) { 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LayoutParams p = (LayoutParams) child.getLayoutParams(); 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (p == null) { 1168aebd28f729fa28016d70551d0372ab7fcd56ee1aAdam Powell p = (AbsListView.LayoutParams) generateDefaultLayoutParams(); 11694df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project child.setLayoutParams(p); 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.viewType = mAdapter.getItemViewType(position); 11720bf88594c43ced48d862d122e3e84967b3b63658Romain Guy p.forceAdd = true; 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childWidthSpec = ViewGroup.getChildMeasureSpec(widthMeasureSpec, 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListPadding.left + mListPadding.right, p.width); 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lpHeight = p.height; 11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childHeightSpec; 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lpHeight > 0) { 11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); 11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.measure(childWidthSpec, childHeightSpec); 11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True to recycle the views used to measure this ListView in 11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * UNSPECIFIED/AT_MOST modes, false otherwise. 11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1191bea95162ca25bd00b0479d93739b6283795c3986Konstantin Lopyrev @ViewDebug.ExportedProperty(category = "list") 11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean recycleOnMeasure() { 11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Measures the height of the given range of children (inclusive) and 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * returns the height with this ListView's padding and divider heights 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * included. If maxHeight is provided, the measuring will stop when the 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * current height reaches maxHeight. 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param widthMeasureSpec The width measure spec to be given to a child's 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link View#measure(int, int)}. 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param startPosition The position of the first child to be shown. 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param endPosition The (inclusive) position of the last child to be 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * shown. Specify {@link #NO_POSITION} if the last child should be 12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the last available child from the adapter. 12089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param maxHeight The maximum height that will be returned (if all the 12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * children don't fit in this value, this value will be 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * returned). 12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param disallowPartialChildPosition In general, whether the returned 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * height should only contain entire children. This is more 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * powerful--it is the first inclusive position at which partial 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * children will not be allowed. Example: it looks nice to have 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * at least 3 completely visible children, and in portrait this 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will most likely fit; but in landscape there could be times 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when even 2 children can not be completely shown, so a value 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of 2 (remember, inclusive) would be good (assuming 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * startPosition is 0). 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The height of this ListView with the given children. 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int measureHeightOfChildren(int widthMeasureSpec, int startPosition, int endPosition, 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int maxHeight, int disallowPartialChildPosition) { 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ListAdapter adapter = mAdapter; 12269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter == null) { 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mListPadding.top + mListPadding.bottom; 12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Include the padding of the list 12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int returnedHeight = mListPadding.top + mListPadding.bottom; 12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int dividerHeight = ((mDividerHeight > 0) && mDivider != null) ? mDividerHeight : 0; 12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The previous height value that was less than maxHeight and contained 12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // no partial children 12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int prevHeightWithoutPartialChild = 0; 12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i; 12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child; 12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mItemCount - 1 since endPosition parameter is inclusive 12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project endPosition = (endPosition == NO_POSITION) ? adapter.getCount() - 1 : endPosition; 12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final AbsListView.RecycleBin recycleBin = mRecycler; 12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean recyle = recycleOnMeasure(); 124321875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy final boolean[] isScrap = mIsScrap; 12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i = startPosition; i <= endPosition; ++i) { 124621875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy child = obtainView(i, isScrap); 12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project measureScrapChild(child, i, widthMeasureSpec); 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (i > 0) { 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Count the divider for all but one child 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project returnedHeight += dividerHeight; 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Recycle the view before we possibly return from the method 12569c3184cc162ee8c10eabd3f996629a9397a1f551Romain Guy if (recyle && recycleBin.shouldRecycleViewType( 12579c3184cc162ee8c10eabd3f996629a9397a1f551Romain Guy ((LayoutParams) child.getLayoutParams()).viewType)) { 1258079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn recycleBin.addScrapView(child, -1); 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project returnedHeight += child.getMeasuredHeight(); 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (returnedHeight >= maxHeight) { 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We went over, figure out which height to return. If returnedHeight > maxHeight, 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // then the i'th position did not fit completely. 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (disallowPartialChildPosition >= 0) // Disallowing is enabled (> -1) 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (i > disallowPartialChildPosition) // We've past the min pos 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (prevHeightWithoutPartialChild > 0) // We have a prev height 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (returnedHeight != maxHeight) // i'th child did not fit completely 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ? prevHeightWithoutPartialChild 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : maxHeight; 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((disallowPartialChildPosition >= 0) && (i >= disallowPartialChildPosition)) { 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project prevHeightWithoutPartialChild = returnedHeight; 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // At this point, we went through the range of children, and they each 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // completely fit, so return the returnedHeight 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return returnedHeight; 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int findMotionRow(int y) { 12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childCount = getChildCount(); 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childCount > 0) { 128884222e04252720cf681032e865db526ce4a612a4Adam Powell if (!mStackFromBottom) { 128984222e04252720cf681032e865db526ce4a612a4Adam Powell for (int i = 0; i < childCount; i++) { 129084222e04252720cf681032e865db526ce4a612a4Adam Powell View v = getChildAt(i); 129184222e04252720cf681032e865db526ce4a612a4Adam Powell if (y <= v.getBottom()) { 129284222e04252720cf681032e865db526ce4a612a4Adam Powell return mFirstPosition + i; 129384222e04252720cf681032e865db526ce4a612a4Adam Powell } 129484222e04252720cf681032e865db526ce4a612a4Adam Powell } 129584222e04252720cf681032e865db526ce4a612a4Adam Powell } else { 129684222e04252720cf681032e865db526ce4a612a4Adam Powell for (int i = childCount - 1; i >= 0; i--) { 129784222e04252720cf681032e865db526ce4a612a4Adam Powell View v = getChildAt(i); 129884222e04252720cf681032e865db526ce4a612a4Adam Powell if (y >= v.getTop()) { 129984222e04252720cf681032e865db526ce4a612a4Adam Powell return mFirstPosition + i; 130084222e04252720cf681032e865db526ce4a612a4Adam Powell } 13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_POSITION; 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Put a specific item at a specific location on the screen and then build 13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * up and down from there. 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position The reference view to use as the starting point 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param top Pixel offset from the top of this view to the top of the 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * reference view. 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The selected view, or null if the selected view is outside the 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * visible area. 13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View fillSpecific(int position, int top) { 13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean tempIsSelected = position == mSelectedPosition; 13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View temp = makeAndAddView(position, top, true, mListPadding.left, tempIsSelected); 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Possibly changed again in fillUp if we add rows above this one. 13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = position; 13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View above; 13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View below; 13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int dividerHeight = mDividerHeight; 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project above = fillUp(position - 1, temp.getTop() - dividerHeight); 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This will correct for the top of the first view not touching the top of the list 13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project below = fillDown(position + 1, temp.getBottom() + dividerHeight); 13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childCount = getChildCount(); 13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childCount > 0) { 13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooHigh(childCount); 13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project below = fillDown(position + 1, temp.getBottom() + dividerHeight); 13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This will correct for the bottom of the last view not touching the bottom of the list 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project above = fillUp(position - 1, temp.getTop() - dividerHeight); 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childCount = getChildCount(); 13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childCount > 0) { 13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project correctTooLow(childCount); 13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (tempIsSelected) { 13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return temp; 13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (above != null) { 13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return above; 13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return below; 13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Check if we have dragged the bottom of the list too high (we have pushed the 13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * top element off the top of the screen when we did not need to). Correct by sliding 13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * everything back down. 13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childCount Number of children 13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void correctTooHigh(int childCount) { 13659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // First see if the last item is visible. If it is not, it is OK for the 13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // top of the list to be pushed up. 13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastPosition = mFirstPosition + childCount - 1; 13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lastPosition == mItemCount - 1 && childCount > 0) { 13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the last child ... 13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View lastChild = getChildAt(childCount - 1); 13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ... and its bottom edge 13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int lastBottom = lastChild.getBottom(); 13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is bottom of our drawable area 13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int end = (mBottom - mTop) - mListPadding.bottom; 13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is how far the bottom edge of the last view is from the bottom of the 13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // drawable area 13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int bottomOffset = end - lastBottom; 13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View firstChild = getChildAt(0); 13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int firstTop = firstChild.getTop(); 13849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make sure we are 1) Too high, and 2) Either there are more rows above the 13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // first row or the first row is scrolled off the top of the drawable area 13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bottomOffset > 0 && (mFirstPosition > 0 || firstTop < mListPadding.top)) { 13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition == 0) { 13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't pull the top too far down 13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottomOffset = Math.min(bottomOffset, mListPadding.top - firstTop); 13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Move everything down 13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(bottomOffset); 13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition > 0) { 13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Fill the gap that was opened above mFirstPosition with more rows, if 13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // possible 13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fillUp(mFirstPosition - 1, firstChild.getTop() - mDividerHeight); 13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Close up the remaining gap 13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Check if we have dragged the bottom of the list too low (we have pushed the 14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * bottom element off the bottom of the screen when we did not need to). Correct by sliding 14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * everything back up. 14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childCount Number of children 14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void correctTooLow(int childCount) { 14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // First see if the first item is visible. If it is not, it is OK for the 14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bottom of the list to be pushed down. 14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition == 0 && childCount > 0) { 14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the first child ... 14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View firstChild = getChildAt(0); 14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ... and its top edge 14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int firstTop = firstChild.getTop(); 14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is top of our drawable area 14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int start = mListPadding.top; 14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is bottom of our drawable area 14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int end = (mBottom - mTop) - mListPadding.bottom; 14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This is how far the top edge of the first view is from the top of the 14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // drawable area 14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int topOffset = firstTop - start; 14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View lastChild = getChildAt(childCount - 1); 14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int lastBottom = lastChild.getBottom(); 14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastPosition = mFirstPosition + childCount - 1; 14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make sure we are 1) Too low, and 2) Either there are more rows below the 14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // last row or the last row is scrolled off the bottom of the drawable area 14396198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy if (topOffset > 0) { 14406198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy if (lastPosition < mItemCount - 1 || lastBottom > end) { 14416198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy if (lastPosition == mItemCount - 1) { 14426198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy // Don't pull the bottom too far up 14436198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy topOffset = Math.min(topOffset, lastBottom - end); 14446198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy } 14456198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy // Move everything up 14466198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy offsetChildrenTopAndBottom(-topOffset); 14476198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy if (lastPosition < mItemCount - 1) { 14486198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy // Fill the gap that was opened below the last position with more rows, if 14496198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy // possible 14506198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy fillDown(lastPosition + 1, lastChild.getBottom() + mDividerHeight); 14516198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy // Close up the remaining gap 14526198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy adjustViewsUpOrDown(); 14536198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy } 14546198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy } else if (lastPosition == mItemCount - 1) { 14556198ae8468668bf7374535c2eeeab8de7f8e7e99Romain Guy adjustViewsUpOrDown(); 14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void layoutChildren() { 14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean blockLayoutRequests = mBlockLayoutRequests; 14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!blockLayoutRequests) { 14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBlockLayoutRequests = true; 14664df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } else { 14674df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project return; 14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.layoutChildren(); 14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAdapter == null) { 14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetList(); 14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childrenTop = mListPadding.top; 14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childrenBottom = mBottom - mTop - mListPadding.bottom; 14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childCount = getChildCount(); 1485ead0d4d8282b35a10bf8816cd99a62a8499d9031Romain Guy int index = 0; 14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int delta = 0; 14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View sel; 14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View oldSel = null; 14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View oldFirst = null; 14919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View newSel = null; 14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 14939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View focusLayoutRestoreView = null; 14949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 149530ee76cf05f785bbf819b71954242c835c597ce1alanv AccessibilityNodeInfo accessibilityFocusLayoutRestoreNode = null; 149630ee76cf05f785bbf819b71954242c835c597ce1alanv View accessibilityFocusLayoutRestoreView = null; 149730ee76cf05f785bbf819b71954242c835c597ce1alanv int accessibilityFocusPosition = INVALID_POSITION; 149830ee76cf05f785bbf819b71954242c835c597ce1alanv 14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remember stuff we will need down below 15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mLayoutMode) { 15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SET_SELECTION: 15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = mNextSelectedPosition - mFirstPosition; 15039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index >= 0 && index < childCount) { 15049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newSel = getChildAt(index); 15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_FORCE_TOP: 15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_FORCE_BOTTOM: 15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SPECIFIC: 15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SYNC: 15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_MOVE_SELECTION: 15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remember the previously selected view 15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project index = mSelectedPosition - mFirstPosition; 15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index >= 0 && index < childCount) { 15179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldSel = getChildAt(index); 15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Remember the previous first child 15219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldFirst = getChildAt(0); 15229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mNextSelectedPosition >= 0) { 15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delta = mNextSelectedPosition - mSelectedPosition; 15259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Caution: newSel might be null 15289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newSel = getChildAt(index + delta); 15299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean dataChanged = mDataChanged; 15339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dataChanged) { 15349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleDataChanged(); 15359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Handle the empty set by removing all views that are visible 15389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // and calling it a day 15399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mItemCount == 0) { 15409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project resetList(); 15419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 15429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1543b45f124a041adf81b3ac8b8dec6b396e751e92d7Romain Guy } else if (mItemCount != mAdapter.getCount()) { 1544b45f124a041adf81b3ac8b8dec6b396e751e92d7Romain Guy throw new IllegalStateException("The content of the adapter has changed but " 1545b45f124a041adf81b3ac8b8dec6b396e751e92d7Romain Guy + "ListView did not receive a notification. Make sure the content of " 1546b45f124a041adf81b3ac8b8dec6b396e751e92d7Romain Guy + "your adapter is not modified from a background thread, but only " 15473940f2df36fbe6a712c88655fc78244977ebd0abOwen Lin + "from the UI thread. [in ListView(" + getId() + ", " + getClass() 15483940f2df36fbe6a712c88655fc78244977ebd0abOwen Lin + ") with Adapter(" + mAdapter.getClass() + ")]"); 15499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectedPositionInt(mNextSelectedPosition); 15529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1553b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette // Remember which child, if any, had accessibility focus. This must 1554b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette // occur before recycling any views, since that will clear 1555b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette // accessibility focus. 1556b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette final ViewRootImpl viewRootImpl = getViewRootImpl(); 1557b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette if (viewRootImpl != null) { 1558b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette final View accessFocusedView = viewRootImpl.getAccessibilityFocusedHost(); 1559b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette if (accessFocusedView != null) { 1560b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette final View accessFocusedChild = findAccessibilityFocusedChild( 1561b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette accessFocusedView); 1562b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette if (accessFocusedChild != null) { 1563b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette if (!dataChanged || isDirectChildHeaderOrFooter(accessFocusedChild)) { 1564b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette // If the views won't be changing, try to maintain 1565b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette // focus on the current view host and (if 1566b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette // applicable) its virtual view. 1567b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette accessibilityFocusLayoutRestoreView = accessFocusedView; 1568b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette accessibilityFocusLayoutRestoreNode = viewRootImpl 1569b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette .getAccessibilityFocusedVirtualView(); 1570b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette } else { 1571b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette // Otherwise, try to maintain focus at the same 1572b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette // position. 1573b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette accessibilityFocusPosition = getPositionForView(accessFocusedChild); 1574b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette } 1575b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette } 1576b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette } 1577b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette } 1578b53c5f6b6f84518145c5cbfd3cc1729758fbc7c0Alan Viverette 15799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Pull all children into the RecycleBin. 15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // These views will be reused if possible 15819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int firstPosition = mFirstPosition; 15829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final RecycleBin recycleBin = mRecycler; 15839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // reset the focus restoration 15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View focusLayoutRestoreDirectChild = null; 15869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Don't put header or footer views into the Recycler. Those are 15889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // already cached in mHeaderViews; 15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dataChanged) { 15909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < childCount; i++) { 1591079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn recycleBin.addScrapView(getChildAt(i), firstPosition+i); 15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 15949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recycleBin.fillActiveViews(childCount, firstPosition); 15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // take focus back to us temporarily to avoid the eventual 15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // call to clear focus when removing the focused child below 1599c6cc0f8c19d9eccf408a443fa2bf668af261dcd0Joe Onorato // from messing things up when ViewAncestor assigns focus back 16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to someone else 16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View focusedChild = getFocusedChild(); 16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (focusedChild != null) { 16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // TODO: in some cases focusedChild.getParent() == null 16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we can remember the focused view to restore after relayout if the 16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // data hasn't changed, or if the focused position is a header or footer 16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!dataChanged || isDirectChildHeaderOrFooter(focusedChild)) { 16084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project focusLayoutRestoreDirectChild = focusedChild; 16094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project // remember the specific view that had focus 16104df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project focusLayoutRestoreView = findFocus(); 16114df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (focusLayoutRestoreView != null) { 16124df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project // tell it we are going to mess with it 16134df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project focusLayoutRestoreView.onStartTemporaryDetach(); 16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestFocus(); 16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Clear out old views 16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project detachAllViewsFromParent(); 1621539ee8716b4f81260bab2e9f3dc5d88d81c99985Adam Powell recycleBin.removeSkippedScrap(); 16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (mLayoutMode) { 16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SET_SELECTION: 16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newSel != null) { 16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillFromSelection(newSel.getTop(), childrenTop, childrenBottom); 16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillFromMiddle(childrenTop, childrenBottom); 16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SYNC: 16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillSpecific(mSyncPosition, mSpecificTop); 16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_FORCE_BOTTOM: 16359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillUp(mItemCount - 1, childrenBottom); 16369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 16379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 16389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_FORCE_TOP: 16399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition = 0; 16409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillFromTop(childrenTop); 16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project adjustViewsUpOrDown(); 16429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 16439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_SPECIFIC: 16449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillSpecific(reconcileSelectedPosition(), mSpecificTop); 16459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case LAYOUT_MOVE_SELECTION: 16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = moveSelection(oldSel, newSel, delta, childrenTop, childrenBottom); 16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childCount == 0) { 16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int position = lookForSelectablePosition(0, true); 16539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectedPositionInt(position); 16549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillFromTop(childrenTop); 16559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 16569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int position = lookForSelectablePosition(mItemCount - 1, false); 16579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectedPositionInt(position); 16589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillUp(mItemCount - 1, childrenBottom); 16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSelectedPosition >= 0 && mSelectedPosition < mItemCount) { 16629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillSpecific(mSelectedPosition, 16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldSel == null ? childrenTop : oldSel.getTop()); 16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mFirstPosition < mItemCount) { 16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillSpecific(mFirstPosition, 16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project oldFirst == null ? childrenTop : oldFirst.getTop()); 16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sel = fillSpecific(0, childrenTop); 16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Flush any cached views that did not get reused above 16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project recycleBin.scrapActiveViews(); 16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sel != null) { 16783616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy // the current selected item should get focus if items 16793616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy // are focusable 16803616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy if (mItemsCanFocus && hasFocus() && !sel.hasFocus()) { 16813616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy final boolean focusWasTaken = (sel == focusLayoutRestoreDirectChild && 16822d8b0170bff5076df7a39e6d01e407accec5f779Adam Powell focusLayoutRestoreView != null && 16833616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy focusLayoutRestoreView.requestFocus()) || sel.requestFocus(); 16843616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy if (!focusWasTaken) { 16853616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy // selected item didn't take focus, fine, but still want 16863616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy // to make sure something else outside of the selected view 16873616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy // has focus 16883616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy final View focused = getFocusedChild(); 16893616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy if (focused != null) { 16903616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy focused.clearFocus(); 16913616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy } 1692079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn positionSelector(INVALID_POSITION, sel); 16933616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy } else { 16943616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy sel.setSelected(false); 16953616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy mSelectorRect.setEmpty(); 16963616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy } 16973616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy } else { 1698079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn positionSelector(INVALID_POSITION, sel); 16993616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy } 17003616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy mSelectedTop = sel.getTop(); 17019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 17023616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy if (mTouchMode > TOUCH_MODE_DOWN && mTouchMode < TOUCH_MODE_SCROLL) { 17033616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy View child = getChildAt(mMotionPosition - mFirstPosition); 1704079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn if (child != null) positionSelector(mMotionPosition, child); 17053616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy } else { 17063616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy mSelectedTop = 0; 17073616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy mSelectorRect.setEmpty(); 17083616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy } 17093616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy 17103616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy // even if there is not selected position, we may need to restore 17113616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy // focus (i.e. something focusable in touch mode) 17123616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy if (hasFocus() && focusLayoutRestoreView != null) { 17133616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy focusLayoutRestoreView.requestFocus(); 17143616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy } 17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 171730ee76cf05f785bbf819b71954242c835c597ce1alanv // Attempt to restore accessibility focus. 171830ee76cf05f785bbf819b71954242c835c597ce1alanv if (accessibilityFocusLayoutRestoreNode != null) { 171930ee76cf05f785bbf819b71954242c835c597ce1alanv accessibilityFocusLayoutRestoreNode.performAction( 172030ee76cf05f785bbf819b71954242c835c597ce1alanv AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS); 172130ee76cf05f785bbf819b71954242c835c597ce1alanv } else if (accessibilityFocusLayoutRestoreView != null) { 172230ee76cf05f785bbf819b71954242c835c597ce1alanv accessibilityFocusLayoutRestoreView.requestAccessibilityFocus(); 172330ee76cf05f785bbf819b71954242c835c597ce1alanv } else if (accessibilityFocusPosition != INVALID_POSITION) { 172430ee76cf05f785bbf819b71954242c835c597ce1alanv // Bound the position within the visible children. 172530ee76cf05f785bbf819b71954242c835c597ce1alanv final int position = MathUtils.constrain( 172630ee76cf05f785bbf819b71954242c835c597ce1alanv (accessibilityFocusPosition - mFirstPosition), 0, (getChildCount() - 1)); 172730ee76cf05f785bbf819b71954242c835c597ce1alanv final View restoreView = getChildAt(position); 172830ee76cf05f785bbf819b71954242c835c597ce1alanv if (restoreView != null) { 172930ee76cf05f785bbf819b71954242c835c597ce1alanv restoreView.requestAccessibilityFocus(); 173030ee76cf05f785bbf819b71954242c835c597ce1alanv } 173130ee76cf05f785bbf819b71954242c835c597ce1alanv } 173230ee76cf05f785bbf819b71954242c835c597ce1alanv 17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // tell focus view we are done mucking with it, if it is still in 17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // our view hierarchy. 17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (focusLayoutRestoreView != null 17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && focusLayoutRestoreView.getWindowToken() != null) { 17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project focusLayoutRestoreView.onFinishTemporaryDetach(); 17389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_NORMAL; 17419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDataChanged = false; 1742161abf3d44feebb8462f7d0cbee81574d666234bAdam Powell if (mPositionScrollAfterLayout != null) { 1743161abf3d44feebb8462f7d0cbee81574d666234bAdam Powell post(mPositionScrollAfterLayout); 1744161abf3d44feebb8462f7d0cbee81574d666234bAdam Powell mPositionScrollAfterLayout = null; 1745161abf3d44feebb8462f7d0cbee81574d666234bAdam Powell } 17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNeedSync = false; 17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setNextSelectedPositionInt(mSelectedPosition); 17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateScrollIndicators(); 17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mItemCount > 0) { 17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkSelectionChanged(); 17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!blockLayoutRequests) { 17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mBlockLayoutRequests = false; 17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 176430ee76cf05f785bbf819b71954242c835c597ce1alanv * @param focusedView the view that has accessibility focus. 176530ee76cf05f785bbf819b71954242c835c597ce1alanv * @return the direct child that contains accessibility focus. 176630ee76cf05f785bbf819b71954242c835c597ce1alanv */ 176730ee76cf05f785bbf819b71954242c835c597ce1alanv private View findAccessibilityFocusedChild(View focusedView) { 176830ee76cf05f785bbf819b71954242c835c597ce1alanv ViewParent viewParent = focusedView.getParent(); 176930ee76cf05f785bbf819b71954242c835c597ce1alanv while ((viewParent instanceof View) && (viewParent != this)) { 177030ee76cf05f785bbf819b71954242c835c597ce1alanv focusedView = (View) viewParent; 177130ee76cf05f785bbf819b71954242c835c597ce1alanv viewParent = viewParent.getParent(); 177230ee76cf05f785bbf819b71954242c835c597ce1alanv } 177330ee76cf05f785bbf819b71954242c835c597ce1alanv if (!(viewParent instanceof View)) { 177430ee76cf05f785bbf819b71954242c835c597ce1alanv return null; 177530ee76cf05f785bbf819b71954242c835c597ce1alanv } 177630ee76cf05f785bbf819b71954242c835c597ce1alanv return focusedView; 177730ee76cf05f785bbf819b71954242c835c597ce1alanv } 177830ee76cf05f785bbf819b71954242c835c597ce1alanv 177930ee76cf05f785bbf819b71954242c835c597ce1alanv /** 17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param child a direct child of this list. 17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether child is a header or footer view. 17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isDirectChildHeaderOrFooter(View child) { 17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<FixedViewInfo> headers = mHeaderViewInfos; 17869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numHeaders = headers.size(); 17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numHeaders; i++) { 17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (child == headers.get(i).view) { 17899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrayList<FixedViewInfo> footers = mFooterViewInfos; 17939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numFooters = footers.size(); 17949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numFooters; i++) { 17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (child == footers.get(i).view) { 17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Obtain the view and add it to our list of children. The view can be made 18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * fresh, converted from an unused view, or used as is if it was in the 18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * recycle bin. 18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position Logical position in the list 18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y Top or bottom edge of the view to add 18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param flow If flow is true, align top edge to y. If false, align bottom 18109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * edge to y. 18119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenLeft Left edge where children should be positioned 18129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selected Is this position selected? 18139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return View that was added 18149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View makeAndAddView(int position, int y, boolean flow, int childrenLeft, 18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean selected) { 18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child; 18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mDataChanged) { 1821079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn // Try to use an existing view for this position 18229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child = mRecycler.getActiveView(position); 18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (child != null) { 18249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Found it -- we're using an existing child 18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This just needs to be positioned 18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setupChild(child, position, y, flow, childrenLeft, selected, true); 18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return child; 18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Make a new view for this position, or convert an unused view if possible 183321875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy child = obtainView(position, mIsScrap); 18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This needs to be positioned and measured 183621875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]); 18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return child; 18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Add a view as a child and make sure it is measured (if necessary) and 18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * positioned properly. 18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param child The view to add 18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position The position of this child 18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y The y position relative to which this view will be positioned 18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param flowDown If true, align top edge to y. If false, align bottom 18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * edge to y. 18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childrenLeft Left edge where children should be positioned 18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selected Is this position selected? 18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param recycled Has this view been pulled from the recycle bin? If so it 18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * does not need to be remeasured. 18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void setupChild(View child, int position, int y, boolean flowDown, int childrenLeft, 18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean selected, boolean recycled) { 18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean isSelected = selected && shouldShowSelector(); 18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean updateChildSelected = isSelected != child.isSelected(); 18593616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy final int mode = mTouchMode; 18603616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy final boolean isPressed = mode > TOUCH_MODE_DOWN && mode < TOUCH_MODE_SCROLL && 18613616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy mMotionPosition == position; 18623616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy final boolean updateChildPressed = isPressed != child.isPressed(); 18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean needToMeasure = !recycled || updateChildSelected || child.isLayoutRequested(); 18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Respect layout params that are already in the view. Otherwise make some up... 18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // noinspection unchecked 18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project AbsListView.LayoutParams p = (AbsListView.LayoutParams) child.getLayoutParams(); 18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (p == null) { 1869aebd28f729fa28016d70551d0372ab7fcd56ee1aAdam Powell p = (AbsListView.LayoutParams) generateDefaultLayoutParams(); 18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p.viewType = mAdapter.getItemViewType(position); 18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18730bf88594c43ced48d862d122e3e84967b3b63658Romain Guy if ((recycled && !p.forceAdd) || (p.recycledHeaderFooter && 1874c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER)) { 18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project attachViewToParent(child, flowDown ? -1 : 0, p); 18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 18770bf88594c43ced48d862d122e3e84967b3b63658Romain Guy p.forceAdd = false; 18784df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project if (p.viewType == AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER) { 18794df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project p.recycledHeaderFooter = true; 18804df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project } 18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addViewInLayout(child, flowDown ? -1 : 0, p, true); 18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (updateChildSelected) { 18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.setSelected(isSelected); 18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 18883616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy if (updateChildPressed) { 18893616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy child.setPressed(isPressed); 18903616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy } 18913616a412cbd620168fd87ce83978d83a9c0621c6Romain Guy 18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null) { 18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (child instanceof Checkable) { 18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((Checkable) child).setChecked(mCheckStates.get(position)); 1895d0fa371f276fde32d81c037006941bc93da0bb03Dianne Hackborn } else if (getContext().getApplicationInfo().targetSdkVersion 1896d0fa371f276fde32d81c037006941bc93da0bb03Dianne Hackborn >= android.os.Build.VERSION_CODES.HONEYCOMB) { 1897d0fa371f276fde32d81c037006941bc93da0bb03Dianne Hackborn child.setActivated(mCheckStates.get(position)); 18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 18999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (needToMeasure) { 19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, 19039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListPadding.left + mListPadding.right, p.width); 19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lpHeight = p.height; 19059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childHeightSpec; 19069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lpHeight > 0) { 19079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); 19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.measure(childWidthSpec, childHeightSpec); 19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 19139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project cleanupLayoutState(child); 19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int w = child.getMeasuredWidth(); 19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int h = child.getMeasuredHeight(); 19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childTop = flowDown ? y : y - h; 19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (needToMeasure) { 19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childRight = childrenLeft + w; 19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childBottom = childTop + h; 19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.layout(childrenLeft, childTop, childRight, childBottom); 19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.offsetLeftAndRight(childrenLeft - child.getLeft()); 19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.offsetTopAndBottom(childTop - child.getTop()); 19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mCachingStarted && !child.isDrawingCacheEnabled()) { 19309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.setDrawingCacheEnabled(true); 19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1932079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn 1933079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn if (recycled && (((AbsListView.LayoutParams)child.getLayoutParams()).scrappedFromPosition) 1934079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn != position) { 1935079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn child.jumpDrawablesToCurrentState(); 1936079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn } 19379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 19409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected boolean canAnimate() { 19419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.canAnimate() && mItemCount > 0; 19429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the currently selected item. If in touch mode, the item will not be selected 19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but it will still be positioned appropriately. If the specified selection position 19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is less than 0, then the item at position 0 will be selected. 19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position Index (starting at 0) of the data item to be selected. 19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 19529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSelection(int position) { 19539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectionFromTop(position, 0); 19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 19579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the selected item and positions the selection y pixels from the top edge 19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of the ListView. (If in touch mode, the item will not be selected but it will 19599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * still be positioned appropriately.) 19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position Index (starting at 0) of the data item to be selected. 19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param y The distance from the top edge of the ListView (plus padding) that the 19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * item will be positioned. 19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSelectionFromTop(int position, int y) { 19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAdapter == null) { 19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!isInTouchMode()) { 19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position = lookForSelectablePosition(position, true); 19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (position >= 0) { 19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setNextSelectedPositionInt(position); 19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResurrectToPosition = position; 19779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (position >= 0) { 19809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_SPECIFIC; 19819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpecificTop = mListPadding.top + y; 19829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mNeedSync) { 19849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSyncPosition = position; 19859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSyncRowId = mAdapter.getItemId(position); 19869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19881fa179ef41c06bd19da70fd9bf95741238791940Adam Powell if (mPositionScroller != null) { 19891fa179ef41c06bd19da70fd9bf95741238791940Adam Powell mPositionScroller.stop(); 19901fa179ef41c06bd19da70fd9bf95741238791940Adam Powell } 19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(); 19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Makes the item at the supplied position selected. 1997f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron * 19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position the position of the item to select 19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void setSelectionInt(int position) { 20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setNextSelectedPositionInt(position); 2003f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron boolean awakeScrollbars = false; 2004f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron 2005f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron final int selectedPosition = mSelectedPosition; 2006f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron 2007f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron if (selectedPosition >= 0) { 2008f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron if (position == selectedPosition - 1) { 2009f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron awakeScrollbars = true; 2010f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron } else if (position == selectedPosition + 1) { 2011f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron awakeScrollbars = true; 2012f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron } 2013f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron } 2014f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron 20151fa179ef41c06bd19da70fd9bf95741238791940Adam Powell if (mPositionScroller != null) { 20161fa179ef41c06bd19da70fd9bf95741238791940Adam Powell mPositionScroller.stop(); 20171fa179ef41c06bd19da70fd9bf95741238791940Adam Powell } 20181fa179ef41c06bd19da70fd9bf95741238791940Adam Powell 20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layoutChildren(); 2020f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron 2021f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron if (awakeScrollbars) { 2022f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron awakenScrollBars(); 2023f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron } 20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Find a position that can be selected (i.e., is not a separator). 20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position The starting position to look at. 20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param lookDown Whether to look down for other positions. 20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The next selectable position starting at position and then searching either up or 20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * down. Returns {@link #INVALID_POSITION} if nothing can be found. 20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lookForSelectablePosition(int position, boolean lookDown) { 20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ListAdapter adapter = mAdapter; 20379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter == null || isInTouchMode()) { 20389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_POSITION; 20399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = adapter.getCount(); 20429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mAreAllItemsSelectable) { 20439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lookDown) { 20449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position = Math.max(0, position); 20459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (position < count && !adapter.isEnabled(position)) { 20469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position++; 20479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 20499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position = Math.min(position, count - 1); 20509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (position >= 0 && !adapter.isEnabled(position)) { 20519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project position--; 20529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (position < 0 || position >= count) { 20569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_POSITION; 20579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return position; 20599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 20609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (position < 0 || position >= count) { 20619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_POSITION; 20629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return position; 20649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 20689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * setSelectionAfterHeaderView set the selection to be the first list item 20699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * after the header views. 20709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 20719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSelectionAfterHeaderView() { 20729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = mHeaderViewInfos.size(); 20739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count > 0) { 20749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNextSelectedPosition = 0; 20759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 20769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAdapter != null) { 20799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelection(count); 20809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 20819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mNextSelectedPosition = count; 20829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_SET_SELECTION; 20839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 20879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 20889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean dispatchKeyEvent(KeyEvent event) { 20899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Dispatch in the normal way 20909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean handled = super.dispatchKeyEvent(event); 20919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!handled) { 20929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If we didn't handle it... 20939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View focused = getFocusedChild(); 20949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (focused != null && event.getAction() == KeyEvent.ACTION_DOWN) { 20959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ... and our focused child didn't handle it 20969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // ... give it to ourselves so we can scroll if necessary 20979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled = onKeyDown(event.getKeyCode(), event); 20989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 20999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return handled; 21019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 21049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onKeyDown(int keyCode, KeyEvent event) { 21059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return commonKey(keyCode, 1, event); 21069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 21099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) { 21109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return commonKey(keyCode, repeatCount, event); 21119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 21149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean onKeyUp(int keyCode, KeyEvent event) { 21159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return commonKey(keyCode, 1, event); 21169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean commonKey(int keyCode, int count, KeyEvent event) { 2119a2b986e72c403f0b2ea593884e3135254bb83d30Adam Powell if (mAdapter == null || !mIsAttached) { 21209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 21219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDataChanged) { 21249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project layoutChildren(); 21259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean handled = false; 21289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int action = event.getAction(); 21299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (action != KeyEvent.ACTION_UP) { 21319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (keyCode) { 21329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case KeyEvent.KEYCODE_DPAD_UP: 21334e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 21348d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded(); 21358d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown if (!handled) { 21364e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown while (count-- > 0) { 21378d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown if (arrowScroll(FOCUS_UP)) { 21388d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = true; 21398d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown } else { 21408d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown break; 21418d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown } 21424e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 21439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21444e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) { 21458d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP); 21469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 21489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case KeyEvent.KEYCODE_DPAD_DOWN: 21504e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 21518d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded(); 21528d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown if (!handled) { 21534e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown while (count-- > 0) { 21548d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown if (arrowScroll(FOCUS_DOWN)) { 21558d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = true; 21568d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown } else { 21578d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown break; 21588d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown } 21594e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 21609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21614e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) { 21628d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN); 21639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 21659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case KeyEvent.KEYCODE_DPAD_LEFT: 21674e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 21684e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown handled = handleHorizontalFocusWithinListItem(View.FOCUS_LEFT); 21694e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 21709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 21714e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 21729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case KeyEvent.KEYCODE_DPAD_RIGHT: 21734e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 21744e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown handled = handleHorizontalFocusWithinListItem(View.FOCUS_RIGHT); 21754e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 21769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 21779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case KeyEvent.KEYCODE_DPAD_CENTER: 21799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case KeyEvent.KEYCODE_ENTER: 21808d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown if (event.hasNoModifiers()) { 21818d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded(); 21828d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown if (!handled 21838d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown && event.getRepeatCount() == 0 && getChildCount() > 0) { 21848d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown keyPressed(); 21858d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = true; 21868d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown } 21879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 21899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 21909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case KeyEvent.KEYCODE_SPACE: 21919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPopup == null || !mPopup.isShowing()) { 21924e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 21938d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_DOWN); 21944e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) { 21958d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_UP); 21969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handled = true; 21989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 21999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 22004e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 22014e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case KeyEvent.KEYCODE_PAGE_UP: 22024e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 22038d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_UP); 22044e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) { 22058d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP); 22064e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 22074e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown break; 22084e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 22094e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case KeyEvent.KEYCODE_PAGE_DOWN: 22104e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 22118d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || pageScroll(FOCUS_DOWN); 22124e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } else if (event.hasModifiers(KeyEvent.META_ALT_ON)) { 22138d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN); 22144e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 22154e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown break; 22164e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 22174e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case KeyEvent.KEYCODE_MOVE_HOME: 22184e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 22198d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_UP); 22204e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 22214e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown break; 22224e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 22234e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case KeyEvent.KEYCODE_MOVE_END: 22244e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 22258d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || fullScroll(FOCUS_DOWN); 22264e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 22274e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown break; 22284e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 22294e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown case KeyEvent.KEYCODE_TAB: 22304e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // XXX Sometimes it is useful to be able to TAB through the items in 22314e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // a ListView sequentially. Unfortunately this can create an 22324e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // asymmetry in TAB navigation order unless the list selection 22334e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // always reverts to the top or bottom when receiving TAB focus from 22344e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // another widget. Leaving this behavior disabled for now but 22354e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown // perhaps it should be configurable (and more comprehensive). 22364e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (false) { 22374e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (event.hasNoModifiers()) { 22388d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_DOWN); 22394e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) { 22408d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown handled = resurrectSelectionIfNeeded() || arrowScroll(FOCUS_UP); 22414e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 22424e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 22434e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown break; 22449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22478d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown if (handled) { 22488d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown return true; 22499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22518d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown if (sendToTextFilter(keyCode, count, event)) { 22529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 22538d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown } 22549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22558d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown switch (action) { 22568d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown case KeyEvent.ACTION_DOWN: 22578d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown return super.onKeyDown(keyCode, event); 22589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22598d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown case KeyEvent.ACTION_UP: 22608d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown return super.onKeyUp(keyCode, event); 22619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22628d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown case KeyEvent.ACTION_MULTIPLE: 22638d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown return super.onKeyMultiple(keyCode, count, event); 22648d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown 22658d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown default: // shouldn't happen 22668d6d3b83fb765eefc6fd38de77f1f45d2523ab89Jeff Brown return false; 22679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 22719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scrolls up or down by the number of items currently present on screen. 22729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 22739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN} 22749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return whether selection was moved 22759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 22769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean pageScroll(int direction) { 22779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nextPage = -1; 22789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean down = false; 22799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == FOCUS_UP) { 22819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextPage = Math.max(0, mSelectedPosition - getChildCount() - 1); 22829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (direction == FOCUS_DOWN) { 22839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextPage = Math.min(mItemCount - 1, mSelectedPosition + getChildCount() - 1); 22849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project down = true; 22859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextPage >= 0) { 22889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int position = lookForSelectablePosition(nextPage, down); 22899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (position >= 0) { 22909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_SPECIFIC; 22919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSpecificTop = mPaddingTop + getVerticalFadingEdgeLength(); 22929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (down && position > mItemCount - getChildCount()) { 22949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_FORCE_BOTTOM; 22959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 22969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 22979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!down && position < getChildCount()) { 22989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_FORCE_TOP; 22999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectionInt(position); 23029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 2303f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron if (!awakenScrollBars()) { 2304f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron invalidate(); 2305f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron } 23069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 23089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 23129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 23159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Go to the last or first item if possible (not worrying about panning across or navigating 23169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * within the internal focus of the currently selected item.) 23179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 23189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN} 23199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 23209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return whether selection was moved 23219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 23229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean fullScroll(int direction) { 23239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean moved = false; 23249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == FOCUS_UP) { 23259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSelectedPosition != 0) { 23269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int position = lookForSelectablePosition(0, true); 23279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (position >= 0) { 23289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_FORCE_TOP; 23299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectionInt(position); 23309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 23319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project moved = true; 23339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (direction == FOCUS_DOWN) { 23359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSelectedPosition < mItemCount - 1) { 23369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int position = lookForSelectablePosition(mItemCount - 1, true); 23379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (position >= 0) { 23389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mLayoutMode = LAYOUT_FORCE_BOTTOM; 23399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectionInt(position); 23409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 23419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project moved = true; 23439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2346f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron if (moved && !awakenScrollBars()) { 2347f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron awakenScrollBars(); 23489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 23499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return moved; 23529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 23559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To avoid horizontal focus searches changing the selected item, we 23569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * manually focus search within the selected item (as applicable), and 23579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * prevent focus from jumping to something within another item. 23589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction one of {View.FOCUS_LEFT, View.FOCUS_RIGHT} 23599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether this consumes the key event. 23609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 23619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean handleHorizontalFocusWithinListItem(int direction) { 23629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction != View.FOCUS_LEFT && direction != View.FOCUS_RIGHT) { 2363304eefa6a33da9b75b4075cc7eb170cf4ced4cdbRomain Guy throw new IllegalArgumentException("direction must be one of" 2364304eefa6a33da9b75b4075cc7eb170cf4ced4cdbRomain Guy + " {View.FOCUS_LEFT, View.FOCUS_RIGHT}"); 23659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numChildren = getChildCount(); 23689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mItemsCanFocus && numChildren > 0 && mSelectedPosition != INVALID_POSITION) { 23699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View selectedView = getSelectedView(); 2370304eefa6a33da9b75b4075cc7eb170cf4ced4cdbRomain Guy if (selectedView != null && selectedView.hasFocus() && 2371304eefa6a33da9b75b4075cc7eb170cf4ced4cdbRomain Guy selectedView instanceof ViewGroup) { 2372304eefa6a33da9b75b4075cc7eb170cf4ced4cdbRomain Guy 23739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View currentFocus = selectedView.findFocus(); 23749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View nextFocus = FocusFinder.getInstance().findNextFocus( 2375304eefa6a33da9b75b4075cc7eb170cf4ced4cdbRomain Guy (ViewGroup) selectedView, currentFocus, direction); 23769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextFocus != null) { 23779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // do the math to get interesting rect in next focus' coordinates 23789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project currentFocus.getFocusedRect(mTempRect); 23799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetDescendantRectToMyCoords(currentFocus, mTempRect); 23809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetRectIntoDescendantCoords(nextFocus, mTempRect); 23819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextFocus.requestFocus(direction, mTempRect)) { 23829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 23839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we are blocking the key from being handled (by returning true) 23869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if the global result is going to be some other view within this 23879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // list. this is to acheive the overall goal of having 23889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // horizontal d-pad navigation remain in the current item. 2389304eefa6a33da9b75b4075cc7eb170cf4ced4cdbRomain Guy final View globalNextFocus = FocusFinder.getInstance().findNextFocus( 2390304eefa6a33da9b75b4075cc7eb170cf4ced4cdbRomain Guy (ViewGroup) getRootView(), currentFocus, direction); 23919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (globalNextFocus != null) { 23929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return isViewAncestorOf(globalNextFocus, this); 23939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 23979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 23989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 23999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 24009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scrolls to the next or previous item if possible. 24019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 24029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction either {@link View#FOCUS_UP} or {@link View#FOCUS_DOWN} 24039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 24049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return whether selection was moved 24059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 24069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean arrowScroll(int direction) { 24079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 24089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInLayout = true; 24099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean handled = arrowScrollImpl(direction); 24109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (handled) { 24119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project playSoundEffect(SoundEffectConstants.getContantForFocusDirection(direction)); 24129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return handled; 24149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } finally { 24159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInLayout = false; 24169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 24202a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell * Used by {@link #arrowScrollImpl(int)} to help determine the next selected position 24212a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell * to move to. This can return a position currently not represented by a view on screen 24222a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell * but only in the direction given. 24232a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell * 24242a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell * @param selectedPos Current selected position to move from 24252a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell * @param direction Direction to move in 24262a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell * @return Desired selected position after moving in the given direction 24272a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell */ 24282a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell private final int nextSelectedPositionForDirection(int selectedPos, int direction) { 24292a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell int nextSelected; 24302a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell if (direction == View.FOCUS_DOWN) { 24312a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell nextSelected = selectedPos != INVALID_POSITION && selectedPos >= mFirstPosition ? 24322a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell selectedPos + 1 : 24332a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell mFirstPosition; 24342a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell } else { 24352a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell final int lastPos = mFirstPosition + getChildCount() - 1; 24362a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell nextSelected = selectedPos != INVALID_POSITION && selectedPos < lastPos? 24372a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell selectedPos - 1 : 24382a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell lastPos; 24392a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell } 24402a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell 24412a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell if (nextSelected < 0 || nextSelected >= mAdapter.getCount()) { 24422a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell return INVALID_POSITION; 24432a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell } 24442a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell return lookForSelectablePosition(nextSelected, direction == View.FOCUS_DOWN); 24452a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell } 24462a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell 24472a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell /** 24489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle an arrow scroll going up or down. Take into account whether items are selectable, 24499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * whether there are focusable items etc. 24509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 24519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction Either {@link android.view.View#FOCUS_UP} or {@link android.view.View#FOCUS_DOWN}. 24529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether any scrolling, selection or focus change occured. 24539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 24549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean arrowScrollImpl(int direction) { 24559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getChildCount() <= 0) { 24569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 24579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View selectedView = getSelectedView(); 2460079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn int selectedPos = mSelectedPosition; 24619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24622a93911b87f7aac6d0dcceabc5983e81befeeda5Adam Powell int nextSelectedPosition = nextSelectedPositionForDirection(selectedPos, direction); 24639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int amountToScroll = amountToScroll(direction, nextSelectedPosition); 24649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if we are moving focus, we may OVERRIDE the default behavior 24669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ArrowScrollFocusResult focusResult = mItemsCanFocus ? arrowScrollFocused(direction) : null; 24679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (focusResult != null) { 24689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nextSelectedPosition = focusResult.getSelectedPosition(); 24699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project amountToScroll = focusResult.getAmountToScroll(); 24709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean needToRedraw = focusResult != null; 24739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextSelectedPosition != INVALID_POSITION) { 24749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleNewSelectionChange(selectedView, direction, nextSelectedPosition, focusResult != null); 24759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setSelectedPositionInt(nextSelectedPosition); 24769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setNextSelectedPositionInt(nextSelectedPosition); 24779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedView = getSelectedView(); 2478079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn selectedPos = nextSelectedPosition; 24799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mItemsCanFocus && focusResult == null) { 24809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // there was no new view found to take focus, make sure we 24819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // don't leave focus with the old selection 24829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View focused = getFocusedChild(); 24839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (focused != null) { 24849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project focused.clearFocus(); 24859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project needToRedraw = true; 24889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project checkSelectionChanged(); 24899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (amountToScroll > 0) { 24929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollListItemsBy((direction == View.FOCUS_UP) ? amountToScroll : -amountToScroll); 24939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project needToRedraw = true; 24949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 24959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 24969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if we didn't find a new focusable, make sure any existing focused 24979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // item that was panned off screen gives up focus. 24989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mItemsCanFocus && (focusResult == null) 24999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && selectedView != null && selectedView.hasFocus()) { 25009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View focused = selectedView.findFocus(); 25011ea6889136cdad8fc01de0665b3a16a4dcb259feMark Brophy if (!isViewAncestorOf(focused, this) || distanceToView(focused) > 0) { 25029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project focused.clearFocus(); 25039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if the current selection is panned off, we need to remove the selection 25079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextSelectedPosition == INVALID_POSITION && selectedView != null 25089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && !isViewAncestorOf(selectedView, this)) { 25099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedView = null; 25109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project hideSelector(); 25119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // but we don't want to set the ressurect position (that would make subsequent 25139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // unhandled key events bring back the item we just scrolled off!) 25149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mResurrectToPosition = INVALID_POSITION; 25159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (needToRedraw) { 25189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selectedView != null) { 2519079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn positionSelector(selectedPos, selectedView); 25209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSelectedTop = selectedView.getTop(); 25219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2522f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron if (!awakenScrollBars()) { 2523f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron invalidate(); 2524f116bf8884b5b58aae261d148003811aa4a7c6e9Mike Cleron } 25259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invokeOnItemScrollListener(); 25269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 25279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 25309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 25339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When selection changes, it is possible that the previously selected or the 25349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * next selected item will change its size. If so, we need to offset some folks, 25359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and re-layout the items as appropriate. 25369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 25379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param selectedView The currently selected view (before changing selection). 25389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * should be <code>null</code> if there was no previous selection. 25399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction Either {@link android.view.View#FOCUS_UP} or 25409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.View#FOCUS_DOWN}. 25419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param newSelectedPosition The position of the next selection. 25429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param newFocusAssigned whether new focus was assigned. This matters because 25439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * when something has focus, we don't want to show selection (ugh). 25449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 25459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleNewSelectionChange(View selectedView, int direction, int newSelectedPosition, 25469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean newFocusAssigned) { 25479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newSelectedPosition == INVALID_POSITION) { 25489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("newSelectedPosition needs to be valid"); 25499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // whether or not we are moving down or up, we want to preserve the 25529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // top of whatever view is on top: 25539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // - moving down: the view that had selection 25549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // - moving up: the view that is getting selection 25559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View topView; 25569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View bottomView; 25579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int topViewIndex, bottomViewIndex; 25589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean topSelected = false; 25599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int selectedIndex = mSelectedPosition - mFirstPosition; 25609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int nextSelectedIndex = newSelectedPosition - mFirstPosition; 25619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == View.FOCUS_UP) { 25629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project topViewIndex = nextSelectedIndex; 25639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottomViewIndex = selectedIndex; 25649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project topView = getChildAt(topViewIndex); 25659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottomView = selectedView; 25669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project topSelected = true; 25679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 25689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project topViewIndex = selectedIndex; 25699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottomViewIndex = nextSelectedIndex; 25709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project topView = selectedView; 25719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottomView = getChildAt(bottomViewIndex); 25729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numChildren = getChildCount(); 25759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // start with top view: is it changing size? 25779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (topView != null) { 25789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project topView.setSelected(!newFocusAssigned && topSelected); 25799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project measureAndAdjustDown(topView, topViewIndex, numChildren); 25809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // is the bottom view changing size? 25839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (bottomView != null) { 25849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottomView.setSelected(!newFocusAssigned && !topSelected); 25859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project measureAndAdjustDown(bottomView, bottomViewIndex, numChildren); 25869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 25889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 25909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Re-measure a child, and if its height changes, lay it out preserving its 25919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * top, and adjust the children below it appropriately. 25929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param child The child 25939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childIndex The view group index of the child. 25949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param numChildren The number of children in the view group. 25959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 25969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void measureAndAdjustDown(View child, int childIndex, int numChildren) { 25979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int oldHeight = child.getHeight(); 25989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project measureItem(child); 25999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (child.getMeasuredHeight() != oldHeight) { 26009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // lay out the view, preserving its top 26019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project relayoutMeasuredItem(child); 26029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // adjust views below appropriately 26049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int heightDelta = child.getMeasuredHeight() - oldHeight; 26059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = childIndex + 1; i < numChildren; i++) { 26069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project getChildAt(i).offsetTopAndBottom(heightDelta); 26079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 26129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Measure a particular list child. 26139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TODO: unify with setUpChild. 26149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param child The child. 26159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 26169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void measureItem(View child) { 26179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ViewGroup.LayoutParams p = child.getLayoutParams(); 26189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (p == null) { 26199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p = new ViewGroup.LayoutParams( 2620980a938c1c9a6a5791a8240e5a1e6638ab28dc77Romain Guy ViewGroup.LayoutParams.MATCH_PARENT, 26219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ViewGroup.LayoutParams.WRAP_CONTENT); 26229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childWidthSpec = ViewGroup.getChildMeasureSpec(mWidthMeasureSpec, 26259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mListPadding.left + mListPadding.right, p.width); 26269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lpHeight = p.height; 26279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childHeightSpec; 26289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lpHeight > 0) { 26299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); 26309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 26319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 26329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.measure(childWidthSpec, childHeightSpec); 26349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 26379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Layout a child that has been measured, preserving its top position. 26389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * TODO: unify with setUpChild. 26399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param child The child. 26409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 26419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void relayoutMeasuredItem(View child) { 26429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int w = child.getMeasuredWidth(); 26439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int h = child.getMeasuredHeight(); 26449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childLeft = mListPadding.left; 26459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childRight = childLeft + w; 26469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childTop = child.getTop(); 26479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childBottom = childTop + h; 26489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project child.layout(childLeft, childTop, childRight, childBottom); 26499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 26529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The amount to preview next items when arrow srolling. 26539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 26549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int getArrowScrollPreviewLength() { 26559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Math.max(MIN_SCROLL_PREVIEW_PIXELS, getVerticalFadingEdgeLength()); 26569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 26599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Determine how much we need to scroll in order to get the next selected view 26609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * visible, with a fading edge showing below as applicable. The amount is 26619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * capped at {@link #getMaxScrollAmount()} . 26629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 26639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction either {@link android.view.View#FOCUS_UP} or 26649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.View#FOCUS_DOWN}. 26659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param nextSelectedPosition The position of the next selection, or 26669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #INVALID_POSITION} if there is no next selectable position 26679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The amount to scroll. Note: this is always positive! Direction 26689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * needs to be taken into account when actually scrolling. 26699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 26709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int amountToScroll(int direction, int nextSelectedPosition) { 26719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int listBottom = getHeight() - mListPadding.bottom; 26729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int listTop = mListPadding.top; 26739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26741ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho int numChildren = getChildCount(); 26759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == View.FOCUS_DOWN) { 26779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int indexToMakeVisible = numChildren - 1; 26789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextSelectedPosition != INVALID_POSITION) { 26799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indexToMakeVisible = nextSelectedPosition - mFirstPosition; 26809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26811ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho while (numChildren <= indexToMakeVisible) { 26821ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho // Child to view is not attached yet. 26831ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho addViewBelow(getChildAt(numChildren - 1), mFirstPosition + numChildren - 1); 26841ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho numChildren++; 26851ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho } 26869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int positionToMakeVisible = mFirstPosition + indexToMakeVisible; 26879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View viewToMakeVisible = getChildAt(indexToMakeVisible); 26889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int goalBottom = listBottom; 26909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (positionToMakeVisible < mItemCount - 1) { 26919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goalBottom -= getArrowScrollPreviewLength(); 26929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (viewToMakeVisible.getBottom() <= goalBottom) { 26959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // item is fully visible. 26969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 26979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 26989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextSelectedPosition != INVALID_POSITION 27009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && (goalBottom - viewToMakeVisible.getTop()) >= getMaxScrollAmount()) { 27019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // item already has enough of it visible, changing selection is good enough 27029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 27039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int amountToScroll = (viewToMakeVisible.getBottom() - goalBottom); 27069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mFirstPosition + numChildren) == mItemCount) { 27089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // last is last in list -> make sure we don't scroll past it 27099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int max = getChildAt(numChildren - 1).getBottom() - listBottom; 27109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project amountToScroll = Math.min(amountToScroll, max); 27119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Math.min(amountToScroll, getMaxScrollAmount()); 27149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 27159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int indexToMakeVisible = 0; 27169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextSelectedPosition != INVALID_POSITION) { 27179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indexToMakeVisible = nextSelectedPosition - mFirstPosition; 27189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27191ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho while (indexToMakeVisible < 0) { 27201ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho // Child to view is not attached yet. 27211ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho addViewAbove(getChildAt(0), mFirstPosition); 27221ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho mFirstPosition--; 27231ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho indexToMakeVisible = nextSelectedPosition - mFirstPosition; 27241ad11b9c6c7b555c27b917f26ecc08446f589284Justin Ho } 27259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int positionToMakeVisible = mFirstPosition + indexToMakeVisible; 27269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View viewToMakeVisible = getChildAt(indexToMakeVisible); 27279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int goalTop = listTop; 27289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (positionToMakeVisible > 0) { 27299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goalTop += getArrowScrollPreviewLength(); 27309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (viewToMakeVisible.getTop() >= goalTop) { 27329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // item is fully visible. 27339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 27349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nextSelectedPosition != INVALID_POSITION && 27379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (viewToMakeVisible.getBottom() - goalTop) >= getMaxScrollAmount()) { 27389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // item already has enough of it visible, changing selection is good enough 27399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 27409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int amountToScroll = (goalTop - viewToMakeVisible.getTop()); 27439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mFirstPosition == 0) { 27449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // first is first in list -> make sure we don't scroll past it 27459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int max = listTop - getChildAt(0).getTop(); 27469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project amountToScroll = Math.min(amountToScroll, max); 27479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Math.min(amountToScroll, getMaxScrollAmount()); 27499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 27539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Holds results of focus aware arrow scrolling. 27549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 27559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static private class ArrowScrollFocusResult { 27569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mSelectedPosition; 27579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mAmountToScroll; 27589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 27609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * How {@link android.widget.ListView#arrowScrollFocused} returns its values. 27619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 27629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void populate(int selectedPosition, int amountToScroll) { 27639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSelectedPosition = selectedPosition; 27649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAmountToScroll = amountToScroll; 27659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getSelectedPosition() { 27689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mSelectedPosition; 27699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getAmountToScroll() { 27729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAmountToScroll; 27739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 27779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction either {@link android.view.View#FOCUS_UP} or 27789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.View#FOCUS_DOWN}. 27799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The position of the next selectable position of the views that 27809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * are currently visible, taking into account the fact that there might 27819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be no selection. Returns {@link #INVALID_POSITION} if there is no 27829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selectable view on screen in the given direction. 27839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 27849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int lookForSelectablePositionOnScreen(int direction) { 27859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int firstPosition = mFirstPosition; 27869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == View.FOCUS_DOWN) { 27879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int startPos = (mSelectedPosition != INVALID_POSITION) ? 27889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSelectedPosition + 1 : 27899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project firstPosition; 27909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startPos >= mAdapter.getCount()) { 27919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_POSITION; 27929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startPos < firstPosition) { 27949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startPos = firstPosition; 27959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 27969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int lastVisiblePos = getLastVisiblePosition(); 27989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ListAdapter adapter = getAdapter(); 27999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int pos = startPos; pos <= lastVisiblePos; pos++) { 28009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter.isEnabled(pos) 28019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && getChildAt(pos - firstPosition).getVisibility() == View.VISIBLE) { 28029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return pos; 28039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 28069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int last = firstPosition + getChildCount() - 1; 28079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int startPos = (mSelectedPosition != INVALID_POSITION) ? 28089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSelectedPosition - 1 : 28099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project firstPosition + getChildCount() - 1; 28105d9d03a0234faa3cffd11502f973057045cafe82Dianne Hackborn if (startPos < 0 || startPos >= mAdapter.getCount()) { 28119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_POSITION; 28129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (startPos > last) { 28149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project startPos = last; 28159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ListAdapter adapter = getAdapter(); 28189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int pos = startPos; pos >= firstPosition; pos--) { 28199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter.isEnabled(pos) 28209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project && getChildAt(pos - firstPosition).getVisibility() == View.VISIBLE) { 28219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return pos; 28229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return INVALID_POSITION; 28269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 28299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Do an arrow scroll based on focus searching. If a new view is 28309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * given focus, return the selection delta and amount to scroll via 28319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * an {@link ArrowScrollFocusResult}, otherwise, return null. 28329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 28339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction either {@link android.view.View#FOCUS_UP} or 28349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.View#FOCUS_DOWN}. 28359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The result if focus has changed, or <code>null</code>. 28369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 28379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ArrowScrollFocusResult arrowScrollFocused(final int direction) { 28389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View selectedView = getSelectedView(); 28399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View newFocus; 28409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selectedView != null && selectedView.hasFocus()) { 28419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View oldFocus = selectedView.findFocus(); 28429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newFocus = FocusFinder.getInstance().findNextFocus(this, oldFocus, direction); 28439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 28449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == View.FOCUS_DOWN) { 28459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean topFadingEdgeShowing = (mFirstPosition > 0); 28469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int listTop = mListPadding.top + 28479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (topFadingEdgeShowing ? getArrowScrollPreviewLength() : 0); 28489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int ySearchPoint = 28499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (selectedView != null && selectedView.getTop() > listTop) ? 28509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedView.getTop() : 28519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project listTop; 28529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTempRect.set(0, ySearchPoint, 0, ySearchPoint); 28539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 28549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean bottomFadingEdgeShowing = 28559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (mFirstPosition + getChildCount() - 1) < mItemCount; 28569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int listBottom = getHeight() - mListPadding.bottom - 28579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (bottomFadingEdgeShowing ? getArrowScrollPreviewLength() : 0); 28589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int ySearchPoint = 28599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (selectedView != null && selectedView.getBottom() < listBottom) ? 28609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selectedView.getBottom() : 28619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project listBottom; 28629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTempRect.set(0, ySearchPoint, 0, ySearchPoint); 28639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newFocus = FocusFinder.getInstance().findNextFocusFromRect(this, mTempRect, direction); 28659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newFocus != null) { 28689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int positionOfNewFocus = positionOfNewFocus(newFocus); 28699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // if the focus change is in a different new position, make sure 28719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we aren't jumping over another selectable position 28729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mSelectedPosition != INVALID_POSITION && positionOfNewFocus != mSelectedPosition) { 28739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int selectablePosition = lookForSelectablePositionOnScreen(direction); 28749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selectablePosition != INVALID_POSITION && 28759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ((direction == View.FOCUS_DOWN && selectablePosition < positionOfNewFocus) || 28769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (direction == View.FOCUS_UP && selectablePosition > positionOfNewFocus))) { 28779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 28789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int focusScroll = amountToScrollToNewFocus(direction, newFocus, positionOfNewFocus); 28829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int maxScrollAmount = getMaxScrollAmount(); 28849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (focusScroll < maxScrollAmount) { 28859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // not moving too far, safe to give next view focus 28869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newFocus.requestFocus(direction); 28879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mArrowScrollFocusResult.populate(positionOfNewFocus, focusScroll); 28889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mArrowScrollFocusResult; 28899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (distanceToView(newFocus) < maxScrollAmount){ 28909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Case to consider: 28919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // too far to get entire next focusable on screen, but by going 28929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // max scroll amount, we are getting it at least partially in view, 28939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so give it focus and scroll the max ammount. 28949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newFocus.requestFocus(direction); 28959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mArrowScrollFocusResult.populate(positionOfNewFocus, maxScrollAmount); 28969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mArrowScrollFocusResult; 28979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 29009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 29039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param newFocus The view that would have focus. 29049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the position that contains newFocus 29059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 29069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int positionOfNewFocus(View newFocus) { 29079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int numChildren = getChildCount(); 29089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numChildren; i++) { 29099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final View child = getChildAt(i); 29109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (isViewAncestorOf(newFocus, child)) { 29119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mFirstPosition + i; 29129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("newFocus is not a child of any of the" 29159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project + " children of the list!"); 29169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 29199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Return true if child is an ancestor of parent, (or equal to the parent). 29209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 29219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isViewAncestorOf(View child, View parent) { 29229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (child == parent) { 29239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 29249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final ViewParent theParent = child.getParent(); 29279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (theParent instanceof ViewGroup) && isViewAncestorOf((View) theParent, parent); 29289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 29319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Determine how much we need to scroll in order to get newFocus in view. 29329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param direction either {@link android.view.View#FOCUS_UP} or 29339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.View#FOCUS_DOWN}. 29349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param newFocus The view that would take focus. 29359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param positionOfNewFocus The position of the list item containing newFocus 29369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The amount to scroll. Note: this is always positive! Direction 29379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * needs to be taken into account when actually scrolling. 29389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 29399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int amountToScrollToNewFocus(int direction, View newFocus, int positionOfNewFocus) { 29409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int amountToScroll = 0; 29419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newFocus.getDrawingRect(mTempRect); 29429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetDescendantRectToMyCoords(newFocus, mTempRect); 29439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (direction == View.FOCUS_UP) { 29449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTempRect.top < mListPadding.top) { 29459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project amountToScroll = mListPadding.top - mTempRect.top; 29469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (positionOfNewFocus > 0) { 29479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project amountToScroll += getArrowScrollPreviewLength(); 29489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 29519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int listBottom = getHeight() - mListPadding.bottom; 29529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTempRect.bottom > listBottom) { 29539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project amountToScroll = mTempRect.bottom - listBottom; 29549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (positionOfNewFocus < mItemCount - 1) { 29559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project amountToScroll += getArrowScrollPreviewLength(); 29569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return amountToScroll; 29609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 29639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Determine the distance to the nearest edge of a view in a particular 2964fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunne * direction. 2965fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunne * 29669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param descendant A descendant of this list. 29679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The distance, or 0 if the nearest edge is already on screen. 29689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 29699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int distanceToView(View descendant) { 29709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int distance = 0; 29719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project descendant.getDrawingRect(mTempRect); 29729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetDescendantRectToMyCoords(descendant, mTempRect); 29739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int listBottom = mBottom - mTop - mListPadding.bottom; 29749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mTempRect.bottom < mListPadding.top) { 29759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project distance = mListPadding.top - mTempRect.bottom; 29769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (mTempRect.top > listBottom) { 29779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project distance = mTempRect.top - listBottom; 29789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return distance; 29809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 29819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 29849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scroll the children by amount, adding a view at the end and removing 29859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * views that fall off as necessary. 29869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 29879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param amount The amount (positive or negative) to scroll. 29889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 29899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void scrollListItemsBy(int amount) { 29909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(amount); 29919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int listBottom = getHeight() - mListPadding.bottom; 29939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int listTop = mListPadding.top; 2994c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project final AbsListView.RecycleBin recycleBin = mRecycler; 29959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (amount < 0) { 29979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // shifted items up 29989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 29999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // may need to pan views into the bottom space 30009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numChildren = getChildCount(); 30019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View last = getChildAt(numChildren - 1); 30029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (last.getBottom() < listBottom) { 30039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int lastVisiblePosition = mFirstPosition + numChildren - 1; 30049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (lastVisiblePosition < mItemCount - 1) { 30059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project last = addViewBelow(last, lastVisiblePosition); 30069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project numChildren++; 30079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 30089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 30099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // may have brought in the last child of the list that is skinnier 30139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // than the fading edge, thereby leaving space at the end. need 30149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to shift back 30159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (last.getBottom() < listBottom) { 30169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(listBottom - last.getBottom()); 30179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // top views may be panned off screen 30209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View first = getChildAt(0); 30219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (first.getBottom() < listTop) { 3022c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project AbsListView.LayoutParams layoutParams = (LayoutParams) first.getLayoutParams(); 3023c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (recycleBin.shouldRecycleViewType(layoutParams.viewType)) { 3024079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn recycleBin.addScrapView(first, mFirstPosition); 3025c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 3026158d6b70ac2f0c8fd7dafe0f865112090fb31699Mattias Niklewski detachViewFromParent(first); 30279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project first = getChildAt(0); 30289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition++; 30299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 30319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // shifted items down 30329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View first = getChildAt(0); 30339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // may need to pan views into top 30359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((first.getTop() > listTop) && (mFirstPosition > 0)) { 30369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project first = addViewAbove(first, mFirstPosition); 30379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFirstPosition--; 30389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // may have brought the very first child of the list in too far and 30419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // need to shift it back 30429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (first.getTop() > listTop) { 30439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetChildrenTopAndBottom(listTop - first.getTop()); 30449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastIndex = getChildCount() - 1; 30479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View last = getChildAt(lastIndex); 30489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // bottom view may be panned off screen 30509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (last.getTop() > listBottom) { 3051c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project AbsListView.LayoutParams layoutParams = (LayoutParams) last.getLayoutParams(); 3052c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project if (recycleBin.shouldRecycleViewType(layoutParams.viewType)) { 3053079e23575024e103358c982152afb7a720ae1a8aDianne Hackborn recycleBin.addScrapView(last, mFirstPosition+lastIndex); 3054c39a6e0c51e182338deb8b63d07933b585134929The Android Open Source Project } 3055158d6b70ac2f0c8fd7dafe0f865112090fb31699Mattias Niklewski detachViewFromParent(last); 30569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project last = getChildAt(--lastIndex); 30579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View addViewAbove(View theView, int position) { 30629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int abovePosition = position - 1; 306321875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy View view = obtainView(abovePosition, mIsScrap); 30649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int edgeOfNewChild = theView.getTop() - mDividerHeight; 306521875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy setupChild(view, abovePosition, edgeOfNewChild, false, mListPadding.left, 306621875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy false, mIsScrap[0]); 30679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return view; 30689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private View addViewBelow(View theView, int position) { 30719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int belowPosition = position + 1; 307221875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy View view = obtainView(belowPosition, mIsScrap); 30739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int edgeOfNewChild = theView.getBottom() + mDividerHeight; 307421875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy setupChild(view, belowPosition, edgeOfNewChild, true, mListPadding.left, 307521875052adddf2b52bc57fea62bf097b8aa04cbfRomain Guy false, mIsScrap[0]); 30769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return view; 30779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 30809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Indicates that the views created by the ListAdapter can contain focusable 30819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * items. 30829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 30839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param itemsCanFocus true if items can get focus, false otherwise 30849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 30859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setItemsCanFocus(boolean itemsCanFocus) { 30869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mItemsCanFocus = itemsCanFocus; 30879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!itemsCanFocus) { 30889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 30899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 30939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether the views created by the ListAdapter can contain focusable 30949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * items. 30959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 30969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean getItemsCanFocus() { 30979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mItemsCanFocus; 30989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 30999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 310124443ea3992e372e47daa50266b0f2ec38cac388Romain Guy public boolean isOpaque() { 31027840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase boolean retValue = (mCachingActive && mIsCacheColorOpaque && mDividerIsOpaque && 31038f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy hasOpaqueScrollbars()) || super.isOpaque(); 31047840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase if (retValue) { 31057840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase // only return true if the list items cover the entire area of the view 31063ba8f5d675831647e45d0ce11507c85dfb5f753bAdam Powell final int listTop = mListPadding != null ? mListPadding.top : mPaddingTop; 31077840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase View first = getChildAt(0); 31087840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase if (first == null || first.getTop() > listTop) { 31097840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase return false; 31107840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase } 31113ba8f5d675831647e45d0ce11507c85dfb5f753bAdam Powell final int listBottom = getHeight() - 31123ba8f5d675831647e45d0ce11507c85dfb5f753bAdam Powell (mListPadding != null ? mListPadding.bottom : mPaddingBottom); 31137840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase View last = getChildAt(getChildCount() - 1); 31147840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase if (last == null || last.getBottom() < listBottom) { 31157840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase return false; 31167840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase } 31177840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase } 31187840055f76f2ba1a0052aee09e578cf9314f5364Chet Haase return retValue; 311924443ea3992e372e47daa50266b0f2ec38cac388Romain Guy } 312024443ea3992e372e47daa50266b0f2ec38cac388Romain Guy 312124443ea3992e372e47daa50266b0f2ec38cac388Romain Guy @Override 312224443ea3992e372e47daa50266b0f2ec38cac388Romain Guy public void setCacheColorHint(int color) { 31238f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy final boolean opaque = (color >>> 24) == 0xFF; 31248f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy mIsCacheColorOpaque = opaque; 31258f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy if (opaque) { 3126a02903fbee6725563da4472bd120f844e9d5518cRomain Guy if (mDividerPaint == null) { 3127a02903fbee6725563da4472bd120f844e9d5518cRomain Guy mDividerPaint = new Paint(); 3128a02903fbee6725563da4472bd120f844e9d5518cRomain Guy } 31298f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy mDividerPaint.setColor(color); 31308f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy } 313124443ea3992e372e47daa50266b0f2ec38cac388Romain Guy super.setCacheColorHint(color); 313224443ea3992e372e47daa50266b0f2ec38cac388Romain Guy } 3133637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3134637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell void drawOverscrollHeader(Canvas canvas, Drawable drawable, Rect bounds) { 3135637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final int height = drawable.getMinimumHeight(); 3136637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3137637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell canvas.save(); 3138637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell canvas.clipRect(bounds); 3139637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3140637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final int span = bounds.bottom - bounds.top; 3141637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (span < height) { 3142637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.top = bounds.bottom - height; 3143637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3144637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3145637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell drawable.setBounds(bounds); 3146637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell drawable.draw(canvas); 3147637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3148637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell canvas.restore(); 3149637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3150637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3151637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell void drawOverscrollFooter(Canvas canvas, Drawable drawable, Rect bounds) { 3152637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final int height = drawable.getMinimumHeight(); 3153637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3154637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell canvas.save(); 3155637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell canvas.clipRect(bounds); 3156637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3157637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final int span = bounds.bottom - bounds.top; 3158637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (span < height) { 3159637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.bottom = bounds.top + height; 3160637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3161637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3162637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell drawable.setBounds(bounds); 3163637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell drawable.draw(canvas); 3164637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3165637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell canvas.restore(); 3166637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3167637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 316824443ea3992e372e47daa50266b0f2ec38cac388Romain Guy @Override 31699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dispatchDraw(Canvas canvas) { 31700211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy if (mCachingStarted) { 31710211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy mCachingActive = true; 31720211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy } 31730211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy 31749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Draw the dividers 31759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int dividerHeight = mDividerHeight; 3176637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final Drawable overscrollHeader = mOverScrollHeader; 3177637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final Drawable overscrollFooter = mOverScrollFooter; 3178637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final boolean drawOverscrollHeader = overscrollHeader != null; 3179637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final boolean drawOverscrollFooter = overscrollFooter != null; 3180bfb5d4b93bb739a012ecec604473838c1343c88aAdam Powell final boolean drawDividers = dividerHeight > 0 && mDivider != null; 31819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3182637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (drawDividers || drawOverscrollHeader || drawOverscrollFooter) { 31839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Only modify the top and bottom in the loop, we set the left and right here 31849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Rect bounds = mTempRect; 31859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bounds.left = mPaddingLeft; 31869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bounds.right = mRight - mLeft - mPaddingRight; 31879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 31889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int count = getChildCount(); 31899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int headerCount = mHeaderViewInfos.size(); 3190bfb5d4b93bb739a012ecec604473838c1343c88aAdam Powell final int itemCount = mItemCount; 3191bfb5d4b93bb739a012ecec604473838c1343c88aAdam Powell final int footerLimit = itemCount - mFooterViewInfos.size() - 1; 31929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean headerDividers = mHeaderDividersEnabled; 31939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean footerDividers = mFooterDividersEnabled; 31949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int first = mFirstPosition; 31952bed22744281a093ee5e76eab531819f3c62b0bfRomain Guy final boolean areAllItemsSelectable = mAreAllItemsSelectable; 31962bed22744281a093ee5e76eab531819f3c62b0bfRomain Guy final ListAdapter adapter = mAdapter; 3197e32edc614e62ac874a969d3cc6bb1e0c0c3f2607Romain Guy // If the list is opaque *and* the background is not, we want to 3198e32edc614e62ac874a969d3cc6bb1e0c0c3f2607Romain Guy // fill a rect where the dividers would be for non-selectable items 3199e32edc614e62ac874a969d3cc6bb1e0c0c3f2607Romain Guy // If the list is opaque and the background is also opaque, we don't 3200e32edc614e62ac874a969d3cc6bb1e0c0c3f2607Romain Guy // need to draw anything since the background will do it for us 3201179de8a37cb886e61264d2b7efd5bd4f29a5b381Romain Guy final boolean fillForMissingDividers = isOpaque() && !super.isOpaque(); 3202e32edc614e62ac874a969d3cc6bb1e0c0c3f2607Romain Guy 3203e32edc614e62ac874a969d3cc6bb1e0c0c3f2607Romain Guy if (fillForMissingDividers && mDividerPaint == null && mIsCacheColorOpaque) { 3204a02903fbee6725563da4472bd120f844e9d5518cRomain Guy mDividerPaint = new Paint(); 3205e32edc614e62ac874a969d3cc6bb1e0c0c3f2607Romain Guy mDividerPaint.setColor(getCacheColorHint()); 3206a02903fbee6725563da4472bd120f844e9d5518cRomain Guy } 32078f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy final Paint paint = mDividerPaint; 32089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32099456655f93f34a11f4b4696212f2649eed0c35dbAdam Powell int effectivePaddingTop = 0; 32109456655f93f34a11f4b4696212f2649eed0c35dbAdam Powell int effectivePaddingBottom = 0; 32119456655f93f34a11f4b4696212f2649eed0c35dbAdam Powell if ((mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK) { 32129456655f93f34a11f4b4696212f2649eed0c35dbAdam Powell effectivePaddingTop = mListPadding.top; 32139456655f93f34a11f4b4696212f2649eed0c35dbAdam Powell effectivePaddingBottom = mListPadding.bottom; 32149456655f93f34a11f4b4696212f2649eed0c35dbAdam Powell } 32159456655f93f34a11f4b4696212f2649eed0c35dbAdam Powell 32169456655f93f34a11f4b4696212f2649eed0c35dbAdam Powell final int listBottom = mBottom - mTop - effectivePaddingBottom + mScrollY; 32179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mStackFromBottom) { 3218637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell int bottom = 0; 32190b8bb4282a7d1afb24f8c4d5beb2ca4ecc731116Adam Powell 3220637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell // Draw top divider or header for overscroll 3221637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final int scrollY = mScrollY; 3222637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (count > 0 && scrollY < 0) { 3223637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (drawOverscrollHeader) { 3224637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.bottom = 0; 3225637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.top = scrollY; 3226637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell drawOverscrollHeader(canvas, overscrollHeader, bounds); 3227637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } else if (drawDividers) { 3228637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.bottom = 0; 3229637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.top = -dividerHeight; 3230637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell drawDivider(canvas, bounds, -1); 3231637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3232637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3233637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 32349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; i++) { 32359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((headerDividers || first + i >= headerCount) && 32369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (footerDividers || first + i < footerLimit)) { 32379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child = getChildAt(i); 32389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bottom = child.getBottom(); 32392bed22744281a093ee5e76eab531819f3c62b0bfRomain Guy // Don't draw dividers next to items that are not enabled 3240637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3241637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (drawDividers && 3242637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell (bottom < listBottom && !(drawOverscrollFooter && i == count - 1))) { 3243637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if ((areAllItemsSelectable || 3244637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell (adapter.isEnabled(first + i) && (i == count - 1 || 3245637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell adapter.isEnabled(first + i + 1))))) { 3246637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.top = bottom; 3247637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.bottom = bottom + dividerHeight; 3248637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell drawDivider(canvas, bounds, i); 3249637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } else if (fillForMissingDividers) { 3250637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.top = bottom; 3251637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.bottom = bottom + dividerHeight; 3252637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell canvas.drawRect(bounds, paint); 3253637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 32549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3257637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3258637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final int overFooterBottom = mBottom + mScrollY; 3259637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (drawOverscrollFooter && first + count == itemCount && 3260637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell overFooterBottom > bottom) { 3261637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.top = bottom; 3262637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.bottom = overFooterBottom; 3263637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell drawOverscrollFooter(canvas, overscrollFooter, bounds); 3264637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 32659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 32669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int top; 32679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3268bfb5d4b93bb739a012ecec604473838c1343c88aAdam Powell final int scrollY = mScrollY; 3269bfb5d4b93bb739a012ecec604473838c1343c88aAdam Powell 3270637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (count > 0 && drawOverscrollHeader) { 3271637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.top = scrollY; 3272637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.bottom = getChildAt(0).getTop(); 3273637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell drawOverscrollHeader(canvas, overscrollHeader, bounds); 3274637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3275637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3276637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final int start = drawOverscrollHeader ? 1 : 0; 3277637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell for (int i = start; i < count; i++) { 32789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((headerDividers || first + i >= headerCount) && 32799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (footerDividers || first + i < footerLimit)) { 32809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View child = getChildAt(i); 32819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project top = child.getTop(); 32822bed22744281a093ee5e76eab531819f3c62b0bfRomain Guy // Don't draw dividers next to items that are not enabled 32830211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy if (top > effectivePaddingTop) { 32848f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy if ((areAllItemsSelectable || 32858f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy (adapter.isEnabled(first + i) && (i == count - 1 || 32868f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy adapter.isEnabled(first + i + 1))))) { 32878f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy bounds.top = top - dividerHeight; 32888f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy bounds.bottom = top; 32898f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy // Give the method the child ABOVE the divider, so we 32908f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy // subtract one from our child 32918f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy // position. Give -1 when there is no child above the 32928f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy // divider. 32938f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy drawDivider(canvas, bounds, i - 1); 3294e32edc614e62ac874a969d3cc6bb1e0c0c3f2607Romain Guy } else if (fillForMissingDividers) { 32958f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy bounds.top = top - dividerHeight; 32968f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy bounds.bottom = top; 32978f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy canvas.drawRect(bounds, paint); 32988f1344f5e7c92f2fd532f65e5584afe0e4cc6b11Romain Guy } 32999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3302bfb5d4b93bb739a012ecec604473838c1343c88aAdam Powell 3303179de8a37cb886e61264d2b7efd5bd4f29a5b381Romain Guy if (count > 0 && scrollY > 0) { 3304637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (drawOverscrollFooter) { 3305637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell final int absListBottom = mBottom; 3306637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.top = absListBottom; 3307637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.bottom = absListBottom + scrollY; 3308637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell drawOverscrollFooter(canvas, overscrollFooter, bounds); 3309637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } else if (drawDividers) { 3310637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.top = listBottom; 3311637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell bounds.bottom = listBottom + dividerHeight; 3312637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell drawDivider(canvas, bounds, -1); 3313637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3314bfb5d4b93bb739a012ecec604473838c1343c88aAdam Powell } 33159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Draw the indicators (these should be drawn above the dividers) and children 33199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.dispatchDraw(canvas); 33209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33220211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy @Override 33230211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy protected boolean drawChild(Canvas canvas, View child, long drawingTime) { 33240211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy boolean more = super.drawChild(canvas, child, drawingTime); 33250211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy if (mCachingActive && child.mCachingFailed) { 33260211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy mCachingActive = false; 33270211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy } 33280211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy return more; 33290211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy } 33300211a0a10d20ec99bd78905ea9cd2960f7beb4c8Romain Guy 33319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 33329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Draws a divider for the given child in the given bounds. 33339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 33349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param canvas The canvas to draw to. 33359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param bounds The bounds of the divider. 33369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childIndex The index of child (of the View) above the divider. 33379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This will be -1 if there is no child above the divider to be 33389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * drawn. 33399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 33409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void drawDivider(Canvas canvas, Rect bounds, int childIndex) { 33419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This widget draws the same divider for all children 33429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Drawable divider = mDivider; 33439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 334495930e13faac8c17dabfaa1478089baa772f091bRomain Guy divider.setBounds(bounds); 33459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project divider.draw(canvas); 33469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 33499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the drawable that will be drawn between each item in the list. 33509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 33519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the current drawable drawn between list elements 33529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 33539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Drawable getDivider() { 33549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDivider; 33559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 33589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the drawable that will be drawn between each item in the list. If the drawable does 33599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not have an intrinsic height, you should also call {@link #setDividerHeight(int)} 33609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 33619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param divider The drawable to use. 33629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 33639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDivider(Drawable divider) { 33649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (divider != null) { 33659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDividerHeight = divider.getIntrinsicHeight(); 33669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 33679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDividerHeight = 0; 33689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDivider = divider; 337024443ea3992e372e47daa50266b0f2ec38cac388Romain Guy mDividerIsOpaque = divider == null || divider.getOpacity() == PixelFormat.OPAQUE; 3371eeb55e673feca137bd0106ca31f9b68509a4ae36Romain Guy requestLayout(); 3372eeb55e673feca137bd0106ca31f9b68509a4ae36Romain Guy invalidate(); 33739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 33769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Returns the height of the divider that will be drawn between each item in the list. 33779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 33789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getDividerHeight() { 33799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mDividerHeight; 33809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 33839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the height of the divider that will be drawn between each item in the list. Calling 33849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this will override the intrinsic height as set by {@link #setDivider(Drawable)} 33859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 33869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param height The new height of the divider in pixels. 33879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 33889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setDividerHeight(int height) { 33899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDividerHeight = height; 3390eeb55e673feca137bd0106ca31f9b68509a4ae36Romain Guy requestLayout(); 3391eeb55e673feca137bd0106ca31f9b68509a4ae36Romain Guy invalidate(); 33929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 33939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 33959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enables or disables the drawing of the divider for header views. 33969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 33979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param headerDividersEnabled True to draw the headers, false otherwise. 33989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 33999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setFooterDividersEnabled(boolean) 34009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #addHeaderView(android.view.View) 34019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 34029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setHeaderDividersEnabled(boolean headerDividersEnabled) { 34039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mHeaderDividersEnabled = headerDividersEnabled; 34049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 34059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 34089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Enables or disables the drawing of the divider for footer views. 34099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 34109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param footerDividersEnabled True to draw the footers, false otherwise. 34119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 34129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setHeaderDividersEnabled(boolean) 34139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #addFooterView(android.view.View) 34149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 34159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFooterDividersEnabled(boolean footerDividersEnabled) { 34169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mFooterDividersEnabled = footerDividersEnabled; 34179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project invalidate(); 34189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419bfb5d4b93bb739a012ecec604473838c1343c88aAdam Powell 3420637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell /** 3421637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * Sets the drawable that will be drawn above all other list content. 3422637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * This area can become visible when the user overscrolls the list. 3423637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * 3424637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * @param header The drawable to use 3425637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell */ 3426637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell public void setOverscrollHeader(Drawable header) { 3427637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell mOverScrollHeader = header; 3428637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell if (mScrollY < 0) { 3429637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell invalidate(); 3430637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3431637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3432637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3433637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell /** 3434637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * @return The drawable that will be drawn above all other list content 3435637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell */ 3436637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell public Drawable getOverscrollHeader() { 3437637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell return mOverScrollHeader; 3438637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3439637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3440637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell /** 3441637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * Sets the drawable that will be drawn below all other list content. 3442637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * This area can become visible when the user overscrolls the list, 3443637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * or when the list's content does not fully fill the container area. 3444637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * 3445637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * @param footer The drawable to use 3446637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell */ 3447637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell public void setOverscrollFooter(Drawable footer) { 3448637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell mOverScrollFooter = footer; 3449637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell invalidate(); 3450637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3451637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 3452637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell /** 3453637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell * @return The drawable that will be drawn below all other list content 3454637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell */ 3455637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell public Drawable getOverscrollFooter() { 3456637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell return mOverScrollFooter; 3457637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell } 3458637d337b58d8eec6de19230a5dd5ca5581c0478dAdam Powell 34599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 34609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) { 34619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); 34629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3463e1bf486846ce7589727ad84440bd9a2d42751055Adam Powell final ListAdapter adapter = mAdapter; 34649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int closetChildIndex = -1; 3465dcce1216b0066f3f9ed1b01a485684e8617e7ea4Adam Powell int closestChildTop = 0; 3466e1bf486846ce7589727ad84440bd9a2d42751055Adam Powell if (adapter != null && gainFocus && previouslyFocusedRect != null) { 34679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project previouslyFocusedRect.offset(mScrollX, mScrollY); 34689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3469d7507834e73f32b4c82839036dc3897a1587e668Adam Powell // Don't cache the result of getChildCount or mFirstPosition here, 3470d7507834e73f32b4c82839036dc3897a1587e668Adam Powell // it could change in layoutChildren. 3471d7507834e73f32b4c82839036dc3897a1587e668Adam Powell if (adapter.getCount() < getChildCount() + mFirstPosition) { 3472c854f281a1c330931a2a03eef802ad7d4521998eAdam Powell mLayoutMode = LAYOUT_NORMAL; 3473c854f281a1c330931a2a03eef802ad7d4521998eAdam Powell layoutChildren(); 3474c854f281a1c330931a2a03eef802ad7d4521998eAdam Powell } 3475c854f281a1c330931a2a03eef802ad7d4521998eAdam Powell 34769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // figure out which item should be selected based on previously 34779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // focused rect 34789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Rect otherRect = mTempRect; 34799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int minDistance = Integer.MAX_VALUE; 34809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childCount = getChildCount(); 3481d7507834e73f32b4c82839036dc3897a1587e668Adam Powell final int firstPosition = mFirstPosition; 34829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < childCount; i++) { 34849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // only consider selectable views 34859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!adapter.isEnabled(firstPosition + i)) { 34869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 34879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View other = getChildAt(i); 34909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project other.getDrawingRect(otherRect); 34919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project offsetDescendantRectToMyCoords(other, otherRect); 34929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int distance = getDistance(previouslyFocusedRect, otherRect, direction); 34939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (distance < minDistance) { 34959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project minDistance = distance; 34969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closetChildIndex = i; 3497dcce1216b0066f3f9ed1b01a485684e8617e7ea4Adam Powell closestChildTop = other.getTop(); 34989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 34999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (closetChildIndex >= 0) { 3503dcce1216b0066f3f9ed1b01a485684e8617e7ea4Adam Powell setSelectionFromTop(closetChildIndex + mFirstPosition, closestChildTop); 35049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 35059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project requestLayout(); 35069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 35119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (non-Javadoc) 35129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 35139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Children specified in XML are assumed to be header views. After we have 35149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * parsed them move them out of the children list and into mHeaderViews. 35159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 35169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 35179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void onFinishInflate() { 35189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onFinishInflate(); 35199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = getChildCount(); 35219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (count > 0) { 35229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; ++i) { 35239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project addHeaderView(getChildAt(i)); 35249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project removeAllViews(); 35269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* (non-Javadoc) 35309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see android.view.View#findViewById(int) 35319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * First look in our children, then in any header and footer views that may be scrolled off. 35329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 35339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 35349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected View findViewTraversal(int id) { 35359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View v; 35369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = super.findViewTraversal(id); 35379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (v == null) { 35389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = findViewInHeadersOrFooters(mHeaderViewInfos, id); 35399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (v != null) { 35409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 35419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = findViewInHeadersOrFooters(mFooterViewInfos, id); 35439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (v != null) { 35449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 35459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 35489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* (non-Javadoc) 35519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 35529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Look in the passed in list of headers or footers for the view. 35539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 35549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View findViewInHeadersOrFooters(ArrayList<FixedViewInfo> where, int id) { 35559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where != null) { 35569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = where.size(); 35579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View v; 35589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < len; i++) { 35609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = where.get(i).view; 35619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!v.isRootNamespace()) { 35639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = v.findViewById(id); 35649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (v != null) { 35669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 35679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 35729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* (non-Javadoc) 35754e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown * @see android.view.View#findViewWithTag(Object) 35769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * First look in our children, then in any header and footer views that may be scrolled off. 35779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 35789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 35799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected View findViewWithTagTraversal(Object tag) { 35809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View v; 35819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = super.findViewWithTagTraversal(tag); 35829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (v == null) { 35834e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown v = findViewWithTagInHeadersOrFooters(mHeaderViewInfos, tag); 35849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (v != null) { 35859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 35869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35884e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown v = findViewWithTagInHeadersOrFooters(mFooterViewInfos, tag); 35899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (v != null) { 35909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 35919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 35949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 35959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 35969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* (non-Javadoc) 35979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 35989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Look in the passed in list of headers or footers for the view with the tag. 35999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 36004e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown View findViewWithTagInHeadersOrFooters(ArrayList<FixedViewInfo> where, Object tag) { 36019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (where != null) { 36029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int len = where.size(); 36039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View v; 36049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < len; i++) { 36069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = where.get(i).view; 36079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!v.isRootNamespace()) { 36099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project v = v.findViewWithTag(tag); 36109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (v != null) { 36129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return v; 36139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 36189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36204e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown /** 36214e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown * @hide 36224e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown * @see android.view.View#findViewByPredicate(Predicate) 36234e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown * First look in our children, then in any header and footer views that may be scrolled off. 36244e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown */ 36254e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown @Override 36264dfbec2665bd5f567d7321f2e88a39e1ab45fdf8Jeff Brown protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) { 36274e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown View v; 36284dfbec2665bd5f567d7321f2e88a39e1ab45fdf8Jeff Brown v = super.findViewByPredicateTraversal(predicate, childToSkip); 36294e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (v == null) { 36304dfbec2665bd5f567d7321f2e88a39e1ab45fdf8Jeff Brown v = findViewByPredicateInHeadersOrFooters(mHeaderViewInfos, predicate, childToSkip); 36314e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (v != null) { 36324e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown return v; 36334e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 36344e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 36354dfbec2665bd5f567d7321f2e88a39e1ab45fdf8Jeff Brown v = findViewByPredicateInHeadersOrFooters(mFooterViewInfos, predicate, childToSkip); 36364e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (v != null) { 36374e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown return v; 36384e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 36394e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 36404e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown return v; 36414e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 36424e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 36434e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown /* (non-Javadoc) 36444e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown * 36454e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown * Look in the passed in list of headers or footers for the first view that matches 36464e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown * the predicate. 36474e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown */ 36484e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown View findViewByPredicateInHeadersOrFooters(ArrayList<FixedViewInfo> where, 36494dfbec2665bd5f567d7321f2e88a39e1ab45fdf8Jeff Brown Predicate<View> predicate, View childToSkip) { 36504e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (where != null) { 36514e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown int len = where.size(); 36524e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown View v; 36534e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 36544e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown for (int i = 0; i < len; i++) { 36554e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown v = where.get(i).view; 36564e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 36574dfbec2665bd5f567d7321f2e88a39e1ab45fdf8Jeff Brown if (v != childToSkip && !v.isRootNamespace()) { 36584e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown v = v.findViewByPredicate(predicate); 36594e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 36604e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown if (v != null) { 36614e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown return v; 36624e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 36634e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 36644e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 36654e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 36664e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown return null; 36674e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown } 36684e6319b73c85082e18d1c532b86336ddd1f8cfaaJeff Brown 36699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3670fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunne * Returns the set of checked items ids. The result is only valid if the 36718f1bfe1a7cef702fd74e5405443e9fdb7c5e7556Adam Powell * choice mode has not been set to {@link #CHOICE_MODE_NONE}. 3672fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunne * 3673fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunne * @return A new array which contains the id of each checked item in the 3674fd3ddfa6f0559eb29eea179690144a7357c34b3dGilles Debunne * list. 36758f1bfe1a7cef702fd74e5405443e9fdb7c5e7556Adam Powell * 3676463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell * @deprecated Use {@link #getCheckedItemIds()} instead. 3677ad28bed52ccabd252149b5297a2d94bacdb388ccRomain Guy */ 36788350f7dbc3a62211b2891f35911e4073d24c4cc5Adam Powell @Deprecated 3679ad28bed52ccabd252149b5297a2d94bacdb388ccRomain Guy public long[] getCheckItemIds() { 3680463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell // Use new behavior that correctly handles stable ID mapping. 3681463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell if (mAdapter != null && mAdapter.hasStableIds()) { 3682463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell return getCheckedItemIds(); 3683463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell } 3684463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell 3685463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell // Old behavior was buggy, but would sort of work for adapters without stable IDs. 3686463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell // Fall back to it to support legacy apps. 3687463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell if (mChoiceMode != CHOICE_MODE_NONE && mCheckStates != null && mAdapter != null) { 3688463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell final SparseBooleanArray states = mCheckStates; 3689463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell final int count = states.size(); 3690463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell final long[] ids = new long[count]; 3691463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell final ListAdapter adapter = mAdapter; 3692463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell 3693463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell int checkedCount = 0; 3694463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell for (int i = 0; i < count; i++) { 3695463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell if (states.valueAt(i)) { 3696463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell ids[checkedCount++] = adapter.getItemId(states.keyAt(i)); 3697463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell } 3698463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell } 3699463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell 3700463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell // Trim array if needed. mCheckStates may contain false values 3701463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell // resulting in checkedCount being smaller than count. 3702463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell if (checkedCount == count) { 3703463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell return ids; 3704463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell } else { 3705463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell final long[] result = new long[checkedCount]; 3706463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell System.arraycopy(ids, 0, result, 0, checkedCount); 3707463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell 3708463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell return result; 3709463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell } 3710463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell } 3711463ceff8a44ec2bf67b0394be7f7e70613a55478Adam Powell return new long[0]; 37128f1bfe1a7cef702fd74e5405443e9fdb7c5e7556Adam Powell } 37138a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 37148a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 37158a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 37168a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityEvent(event); 37178a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov event.setClassName(ListView.class.getName()); 37188a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 37198a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 37208a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 37218a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 37228a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityNodeInfo(info); 37238a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov info.setClassName(ListView.class.getName()); 37248a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 37259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3726