1da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownpackage android.support.v7.internal.widget;
279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes/*
479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * Copyright (C) 2006 The Android Open Source Project
579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *
679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * Licensed under the Apache License, Version 2.0 (the "License");
779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * you may not use this file except in compliance with the License.
879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * You may obtain a copy of the License at
979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *
1079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *      http://www.apache.org/licenses/LICENSE-2.0
1179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *
1279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * Unless required by applicable law or agreed to in writing, software
1379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * distributed under the License is distributed on an "AS IS" BASIS,
1479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * See the License for the specific language governing permissions and
1679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * limitations under the License.
1779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes */
1879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
1979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.content.Context;
2079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.database.DataSetObserver;
2179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.os.Parcelable;
2279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.os.SystemClock;
2379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.util.AttributeSet;
2479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.util.SparseArray;
2579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.view.ContextMenu;
2679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.view.ContextMenu.ContextMenuInfo;
2779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.view.SoundEffectConstants;
2879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.view.View;
2979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.view.ViewDebug;
3079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.view.ViewGroup;
3179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.view.accessibility.AccessibilityEvent;
3279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.widget.Adapter;
3379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.widget.AdapterView;
3479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesimport android.widget.ListView;
3579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
3679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
3779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes/**
3879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * An AdapterView is a view whose children are determined by an {@link android.widget.Adapter}.
3979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *
4079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * <p>
4179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * See {@link ListView}, {@link android.widget.GridView}, {@link android.widget.Spinner} and
4279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *      {@link android.widget.Gallery} for commonly used subclasses of AdapterView.
4379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes *
4479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * <div class="special reference">
4579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * <h3>Developer Guides</h3>
4679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * <p>For more information about using AdapterView, read the
4779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * <a href="{@docRoot}guide/topics/ui/binding.html">Binding to Data with AdapterView</a>
4879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes * developer guide.</p></div>
4979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes */
5079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banesabstract class AdapterViewICS<T extends Adapter> extends ViewGroup {
5179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
5279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
5379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The item view type returned by {@link Adapter#getItemViewType(int)} when
5479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * the adapter does not want the item's view recycled.
5579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
5679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    static final int ITEM_VIEW_TYPE_IGNORE = -1;
5779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
5879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
5979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The item view type returned by {@link Adapter#getItemViewType(int)} when
6079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * the item is a header or footer.
6179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
6279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    static final int ITEM_VIEW_TYPE_HEADER_OR_FOOTER = -2;
6379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
6479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
6579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The position of the first child displayed
6679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
6779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @ViewDebug.ExportedProperty(category = "scrolling")
6879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int mFirstPosition = 0;
6979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
7079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
7179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The offset in pixels from the top of the AdapterView to the top
7279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * of the view to select during the next layout.
7379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
7479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int mSpecificTop;
7579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
7679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
7779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Position from which to start looking for mSyncRowId
7879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
7979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int mSyncPosition;
8079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
8179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
8279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Row id to look for when data has changed
8379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
8479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    long mSyncRowId = INVALID_ROW_ID;
8579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
8679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
8779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Height of the view when mSyncPosition and mSyncRowId where set
8879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
8979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    long mSyncHeight;
9079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
9179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
9279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * True if we need to sync to mSyncRowId
9379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
9479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    boolean mNeedSync = false;
9579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
9679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
9779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Indicates whether to sync based on the selection or position. Possible
9879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * values are {@link #SYNC_SELECTED_POSITION} or
9979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * {@link #SYNC_FIRST_POSITION}.
10079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
10179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int mSyncMode;
10279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
10379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
10479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Our height after the last layout
10579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
10679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private int mLayoutHeight;
10779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
10879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
10979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Sync based on the selected child
11079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
11179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    static final int SYNC_SELECTED_POSITION = 0;
11279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
11379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
11479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Sync based on the first child displayed
11579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
11679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    static final int SYNC_FIRST_POSITION = 1;
11779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
11879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
11979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Maximum amount of time to spend in {@link #findSyncPosition()}
12079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
12179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    static final int SYNC_MAX_DURATION_MILLIS = 100;
12279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
12379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
12479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Indicates that this view is currently being laid out.
12579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
12679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    boolean mInLayout = false;
12779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
12879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
12979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The listener that receives notifications when an item is selected.
13079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
13179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    OnItemSelectedListener mOnItemSelectedListener;
13279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
13379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
13479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The listener that receives notifications when an item is clicked.
13579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
13679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    OnItemClickListener mOnItemClickListener;
13779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
13879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
13979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The listener that receives notifications when an item is long clicked.
14079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
14179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    OnItemLongClickListener mOnItemLongClickListener;
14279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
14379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
14479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * True if the data has changed since the last layout
14579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
14679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    boolean mDataChanged;
14779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
14879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
14979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The position within the adapter's data set of the item to select
15079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * during the next layout.
15179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
15279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @ViewDebug.ExportedProperty(category = "list")
15379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int mNextSelectedPosition = INVALID_POSITION;
15479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
15579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
15679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The item id of the item to select during the next layout.
15779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
15879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    long mNextSelectedRowId = INVALID_ROW_ID;
15979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
16079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
16179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The position within the adapter's data set of the currently selected item.
16279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
16379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @ViewDebug.ExportedProperty(category = "list")
16479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int mSelectedPosition = INVALID_POSITION;
16579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
16679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
16779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The item id of the currently selected item.
16879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
16979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    long mSelectedRowId = INVALID_ROW_ID;
17079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
17179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
17279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * View to show if there are no items to show.
17379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
17479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private View mEmptyView;
17579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
17679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
17779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The number of items in the current adapter.
17879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
17979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @ViewDebug.ExportedProperty(category = "list")
18079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int mItemCount;
18179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
18279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
18379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The number of items in the adapter before a data changed event occurred.
18479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
18579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int mOldItemCount;
18679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
18779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
18879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Represents an invalid position. All valid positions are in the range 0 to 1 less than the
18979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * number of items in the current adapter.
19079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
19179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public static final int INVALID_POSITION = -1;
19279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
19379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
19479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Represents an empty or invalid row id
19579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
19679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public static final long INVALID_ROW_ID = Long.MIN_VALUE;
19779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
19879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
19979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The last selected position we used when notifying
20079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
20179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int mOldSelectedPosition = INVALID_POSITION;
20279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
20379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
20479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * The id of the last selected position we used when notifying
20579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
20679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    long mOldSelectedRowId = INVALID_ROW_ID;
20779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
20879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
20979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Indicates what focusable state is requested when calling setFocusable().
21079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * In addition to this, this view has other criteria for actually
21179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * determining the focusable state (such as whether its empty or the text
21279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * filter is shown).
21379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
21479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @see #setFocusable(boolean)
21579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @see #checkFocus()
21679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
21779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private boolean mDesiredFocusableState;
21879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private boolean mDesiredFocusableInTouchModeState;
21979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
22079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private SelectionNotifier mSelectionNotifier;
22179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
22279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * When set to true, calls to requestLayout() will not propagate up the parent hierarchy.
22379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * This is used to layout the children during a layout pass.
22479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
22579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    boolean mBlockLayoutRequests = false;
22679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
22779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    AdapterViewICS(Context context) {
22879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super(context);
22979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
23079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
23179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    AdapterViewICS(Context context, AttributeSet attrs) {
23279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super(context, attrs);
23379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
23479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
23579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    AdapterViewICS(Context context, AttributeSet attrs, int defStyle) {
23679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super(context, attrs, defStyle);
23779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
23879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
23979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
24079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Interface definition for a callback to be invoked when an item in this
24179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * AdapterView has been clicked.
24279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
24379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public interface OnItemClickListener {
24479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
24579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
24679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * Callback method to be invoked when an item in this AdapterView has
24779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * been clicked.
24879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * <p>
24979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * Implementers can call getItemAtPosition(position) if they need
25079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * to access the data associated with the selected item.
25179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         *
25279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param parent The AdapterView where the click happened.
25379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param view The view within the AdapterView that was clicked (this
25479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         *            will be a view provided by the adapter)
25579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param position The position of the view in the adapter.
25679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param id The row id of the item that was clicked.
25779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
25879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        void onItemClick(AdapterViewICS<?> parent, View view, int position, long id);
25979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
26079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
26179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    class OnItemClickListenerWrapper implements AdapterView.OnItemClickListener {
26279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
26379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        private final OnItemClickListener mWrappedListener;
26479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
26579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public OnItemClickListenerWrapper(OnItemClickListener listener) {
26679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mWrappedListener = listener;
26779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
26879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
26979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        @Override
27079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
27179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mWrappedListener.onItemClick(AdapterViewICS.this, view, position, id);
27279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
27379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
27479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
27579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
27679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Register a callback to be invoked when an item in this AdapterView has
27779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * been clicked.
27879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
27979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param listener The callback that will be invoked.
28079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
28179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setOnItemClickListener(OnItemClickListener listener) {
28279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mOnItemClickListener = listener;
28379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
28479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
28579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
28679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The callback to be invoked with an item in this AdapterView has
28779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *         been clicked, or null id no callback has been set.
28879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
28979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public final OnItemClickListener getOnItemClickListener() {
29079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return mOnItemClickListener;
29179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
29279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
29379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
29479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Call the OnItemClickListener, if it is defined.
29579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
29679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param view The view within the AdapterView that was clicked.
29779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param position The position of the view in the adapter.
29879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param id The row id of the item that was clicked.
29979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return True if there was an assigned OnItemClickListener that was
30079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *         called, false otherwise is returned.
30179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
30279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public boolean performItemClick(View view, int position, long id) {
30379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mOnItemClickListener != null) {
30479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            playSoundEffect(SoundEffectConstants.CLICK);
30579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (view != null) {
30679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
30779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
30879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mOnItemClickListener.onItemClick(this, view, position, id);
30979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return true;
31079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
31179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
31279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return false;
31379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
31479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
31579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
31679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Interface definition for a callback to be invoked when an item in this
31779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * view has been clicked and held.
31879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
31979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public interface OnItemLongClickListener {
32079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
32179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * Callback method to be invoked when an item in this view has been
32279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * clicked and held.
32379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         *
32479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * Implementers can call getItemAtPosition(position) if they need to access
32579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * the data associated with the selected item.
32679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         *
32779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param parent The AbsListView where the click happened
32879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param view The view within the AbsListView that was clicked
32979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param position The position of the view in the list
33079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param id The row id of the item that was clicked
33179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         *
33279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @return true if the callback consumed the long click, false otherwise
33379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
33479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        boolean onItemLongClick(AdapterViewICS<?> parent, View view, int position, long id);
33579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
33679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
33779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
33879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
33979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Register a callback to be invoked when an item in this AdapterView has
34079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * been clicked and held
34179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
34279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param listener The callback that will run
34379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
34479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setOnItemLongClickListener(OnItemLongClickListener listener) {
34579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (!isLongClickable()) {
34679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setLongClickable(true);
34779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
34879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mOnItemLongClickListener = listener;
34979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
35079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
35179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
35279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The callback to be invoked with an item in this AdapterView has
35379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *         been clicked and held, or null id no callback as been set.
35479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
35579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public final OnItemLongClickListener getOnItemLongClickListener() {
35679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return mOnItemLongClickListener;
35779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
35879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
35979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
36079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Interface definition for a callback to be invoked when
36179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * an item in this view has been selected.
36279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
36379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public interface OnItemSelectedListener {
36479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
36579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * <p>Callback method to be invoked when an item in this view has been
36679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * selected. This callback is invoked only when the newly selected
36779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * position is different from the previously selected position or if
36879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * there was no selected item.</p>
36979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         *
37079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * Impelmenters can call getItemAtPosition(position) if they need to access the
37179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * data associated with the selected item.
37279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         *
37379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param parent The AdapterView where the selection happened
37479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param view The view within the AdapterView that was clicked
37579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param position The position of the view in the adapter
37679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param id The row id of the item that is selected
37779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
37879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        void onItemSelected(AdapterViewICS<?> parent, View view, int position, long id);
37979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
38079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
38179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * Callback method to be invoked when the selection disappears from this
38279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * view. The selection can disappear for instance when touch is activated
38379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * or when the adapter becomes empty.
38479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         *
38579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * @param parent The AdapterView that now contains no selected item.
38679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
38779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        void onNothingSelected(AdapterViewICS<?> parent);
38879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
38979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
39079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
39179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
39279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Register a callback to be invoked when an item in this AdapterView has
39379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * been selected.
39479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
39579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param listener The callback that will run
39679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
39779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setOnItemSelectedListener(OnItemSelectedListener listener) {
39879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mOnItemSelectedListener = listener;
39979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
40079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
40179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public final OnItemSelectedListener getOnItemSelectedListener() {
40279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return mOnItemSelectedListener;
40379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
40479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
40579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
40679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Extra menu information provided to the
40779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * {@link android.view.View.OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo) }
40879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * callback when a context menu is brought up for this AdapterView.
40979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
41079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
41179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public static class AdapterContextMenuInfo implements ContextMenu.ContextMenuInfo {
41279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
41379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public AdapterContextMenuInfo(View targetView, int position, long id) {
41479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            this.targetView = targetView;
41579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            this.position = position;
41679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            this.id = id;
41779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
41879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
41979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
42079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * The child view for which the context menu is being displayed. This
42179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * will be one of the children of this AdapterView.
42279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
42379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public View targetView;
42479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
42579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
42679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * The position in the adapter for which the context menu is being
42779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * displayed.
42879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
42979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public int position;
43079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
43179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        /**
43279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         * The row id of the item for which the context menu is being displayed.
43379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes         */
43479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public long id;
43579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
43679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
43779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
43879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Returns the adapter currently associated with this widget.
43979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
44079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The adapter used to provide this view's content.
44179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
44279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public abstract T getAdapter();
44379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
44479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
44579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Sets the adapter that provides the data and the views to represent the data
44679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * in this widget.
44779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
44879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param adapter The adapter to use to create this view's content.
44979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
45079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public abstract void setAdapter(T adapter);
45179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
45279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
45379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * This method is not supported and throws an UnsupportedOperationException when called.
45479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
45579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param child Ignored.
45679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
45779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @throws UnsupportedOperationException Every time this method is invoked.
45879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
45979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
46079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void addView(View child) {
46179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        throw new UnsupportedOperationException("addView(View) is not supported in AdapterView");
46279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
46379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
46479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
46579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * This method is not supported and throws an UnsupportedOperationException when called.
46679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
46779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param child Ignored.
46879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param index Ignored.
46979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
47079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @throws UnsupportedOperationException Every time this method is invoked.
47179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
47279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
47379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void addView(View child, int index) {
47479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        throw new UnsupportedOperationException("addView(View, int) is not supported in AdapterView");
47579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
47679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
47779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
47879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * This method is not supported and throws an UnsupportedOperationException when called.
47979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
48079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param child Ignored.
48179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param params Ignored.
48279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
48379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @throws UnsupportedOperationException Every time this method is invoked.
48479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
48579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
48679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void addView(View child, LayoutParams params) {
48779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        throw new UnsupportedOperationException("addView(View, LayoutParams) "
48879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                + "is not supported in AdapterView");
48979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
49079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
49179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
49279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * This method is not supported and throws an UnsupportedOperationException when called.
49379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
49479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param child Ignored.
49579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param index Ignored.
49679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param params Ignored.
49779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
49879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @throws UnsupportedOperationException Every time this method is invoked.
49979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
50079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
50179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void addView(View child, int index, LayoutParams params) {
50279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        throw new UnsupportedOperationException("addView(View, int, LayoutParams) "
50379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                + "is not supported in AdapterView");
50479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
50579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
50679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
50779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * This method is not supported and throws an UnsupportedOperationException when called.
50879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
50979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param child Ignored.
51079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
51179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @throws UnsupportedOperationException Every time this method is invoked.
51279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
51379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
51479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void removeView(View child) {
51579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        throw new UnsupportedOperationException("removeView(View) is not supported in AdapterView");
51679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
51779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
51879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
51979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * This method is not supported and throws an UnsupportedOperationException when called.
52079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
52179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param index Ignored.
52279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
52379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @throws UnsupportedOperationException Every time this method is invoked.
52479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
52579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
52679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void removeViewAt(int index) {
52779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        throw new UnsupportedOperationException("removeViewAt(int) is not supported in AdapterView");
52879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
52979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
53079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
53179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * This method is not supported and throws an UnsupportedOperationException when called.
53279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
53379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @throws UnsupportedOperationException Every time this method is invoked.
53479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
53579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
53679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void removeAllViews() {
53779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        throw new UnsupportedOperationException("removeAllViews() is not supported in AdapterView");
53879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
53979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
54079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
54179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
54279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mLayoutHeight = getHeight();
54379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
54479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
54579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
54679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Return the position of the currently selected item within the adapter's data set
54779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
54879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return int Position (starting at 0), or {@link #INVALID_POSITION} if there is nothing selected.
54979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
55079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @ViewDebug.CapturedViewProperty
55179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public int getSelectedItemPosition() {
55279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return mNextSelectedPosition;
55379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
55479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
55579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
55679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The id corresponding to the currently selected item, or {@link #INVALID_ROW_ID}
55779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * if nothing is selected.
55879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
55979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @ViewDebug.CapturedViewProperty
56079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public long getSelectedItemId() {
56179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return mNextSelectedRowId;
56279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
56379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
56479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
56579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The view corresponding to the currently selected item, or null
56679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * if nothing is selected
56779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
56879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public abstract View getSelectedView();
56979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
57079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
57179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The data corresponding to the currently selected item, or
57279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * null if there is nothing selected.
57379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
57479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public Object getSelectedItem() {
57579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        T adapter = getAdapter();
57679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int selection = getSelectedItemPosition();
57779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (adapter != null && adapter.getCount() > 0 && selection >= 0) {
57879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return adapter.getItem(selection);
57979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        } else {
58079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return null;
58179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
58279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
58379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
58479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
58579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The number of items owned by the Adapter associated with this
58679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *         AdapterView. (This is the number of data items, which may be
58779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *         larger than the number of visible views.)
58879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
58979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @ViewDebug.CapturedViewProperty
59079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public int getCount() {
59179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return mItemCount;
59279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
59379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
59479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
59579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Get the position within the adapter's data set for the view, where view is a an adapter item
59679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * or a descendant of an adapter item.
59779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
59879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param view an adapter item, or a descendant of an adapter item. This must be visible in this
59979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *        AdapterView at the time of the call.
60079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return the position within the adapter's data set of the view, or {@link #INVALID_POSITION}
60179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *         if the view does not correspond to a list item (or it is not currently visible).
60279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
60379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public int getPositionForView(View view) {
60479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        View listItem = view;
60579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        try {
60679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            View v;
60779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            while (!(v = (View) listItem.getParent()).equals(this)) {
60879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                listItem = v;
60979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
61079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        } catch (ClassCastException e) {
61179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            // We made it up to the window without find this list view
61279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return INVALID_POSITION;
61379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
61479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
61579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Search the children for the list item
61679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final int childCount = getChildCount();
61779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        for (int i = 0; i < childCount; i++) {
61879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (getChildAt(i).equals(listItem)) {
61979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                return mFirstPosition + i;
62079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
62179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
62279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
62379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Child not found!
62479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return INVALID_POSITION;
62579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
62679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
62779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
62879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Returns the position within the adapter's data set for the first item
62979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * displayed on screen.
63079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
63179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The position within the adapter's data set
63279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
63379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public int getFirstVisiblePosition() {
63479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return mFirstPosition;
63579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
63679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
63779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
63879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Returns the position within the adapter's data set for the last item
63979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * displayed on screen.
64079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
64179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The position within the adapter's data set
64279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
64379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public int getLastVisiblePosition() {
64479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return mFirstPosition + getChildCount() - 1;
64579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
64679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
64779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
64879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Sets the currently selected item. To support accessibility subclasses that
64979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * override this method must invoke the overriden super method first.
65079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
65179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param position Index (starting at 0) of the data item to be selected.
65279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
65379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public abstract void setSelection(int position);
65479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
65579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
65679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Sets the view to show if the adapter is empty
65779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
65879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setEmptyView(View emptyView) {
65979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mEmptyView = emptyView;
66079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
66179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final T adapter = getAdapter();
66279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final boolean empty = ((adapter == null) || adapter.isEmpty());
66379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        updateEmptyStatus(empty);
66479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
66579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
66679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
66779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * When the current adapter is empty, the AdapterView can display a special view
66879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * call the empty view. The empty view is used to provide feedback to the user
66979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * that no data is available in this AdapterView.
67079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
67179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The view to show if the adapter is empty.
67279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
67379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public View getEmptyView() {
67479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return mEmptyView;
67579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
67679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
67779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
67879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Indicates whether this view is in filter mode. Filter mode can for instance
67979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * be enabled by a user when typing on the keyboard.
68079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
68179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return True if the view is in filter mode, false otherwise.
68279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
68379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    boolean isInFilterMode() {
68479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return false;
68579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
68679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
68779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
68879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setFocusable(boolean focusable) {
68979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final T adapter = getAdapter();
69079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final boolean empty = adapter == null || adapter.getCount() == 0;
69179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
69279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mDesiredFocusableState = focusable;
69379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (!focusable) {
69479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mDesiredFocusableInTouchModeState = false;
69579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
69679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
69779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super.setFocusable(focusable && (!empty || isInFilterMode()));
69879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
69979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
70079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
70179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setFocusableInTouchMode(boolean focusable) {
70279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final T adapter = getAdapter();
70379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final boolean empty = adapter == null || adapter.getCount() == 0;
70479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
70579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mDesiredFocusableInTouchModeState = focusable;
70679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (focusable) {
70779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mDesiredFocusableState = true;
70879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
70979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
71079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super.setFocusableInTouchMode(focusable && (!empty || isInFilterMode()));
71179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
71279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
71379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    void checkFocus() {
71479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final T adapter = getAdapter();
71579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final boolean empty = adapter == null || adapter.getCount() == 0;
71679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final boolean focusable = !empty || isInFilterMode();
71779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // The order in which we set focusable in touch mode/focusable may matter
71879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // for the client, see View.setFocusableInTouchMode() comments for more
71979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // details
72079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super.setFocusableInTouchMode(focusable && mDesiredFocusableInTouchModeState);
72179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super.setFocusable(focusable && mDesiredFocusableState);
72279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mEmptyView != null) {
72379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            updateEmptyStatus((adapter == null) || adapter.isEmpty());
72479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
72579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
72679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
72779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
72879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Update the status of the list based on the empty parameter.  If empty is true and
72979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * we have an empty view, display it.  In all the other cases, make sure that the listview
73079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * is VISIBLE and that the empty view is GONE (if it's not null).
73179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
73279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private void updateEmptyStatus(boolean empty) {
73379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (isInFilterMode()) {
73479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            empty = false;
73579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
73679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
73779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (empty) {
73879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (mEmptyView != null) {
73979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mEmptyView.setVisibility(View.VISIBLE);
74079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                setVisibility(View.GONE);
74179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            } else {
74279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // If the caller just removed our empty view, make sure the list view is visible
74379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                setVisibility(View.VISIBLE);
74479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
74579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
74679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            // We are now GONE, so pending layouts will not be dispatched.
74779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            // Force one here to make sure that the state of the list matches
74879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            // the state of the adapter.
74979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (mDataChanged) {
75079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                this.onLayout(false, getLeft(), getTop(), getRight(), getBottom());
75179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
75279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        } else {
75379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (mEmptyView != null) mEmptyView.setVisibility(View.GONE);
75479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            setVisibility(View.VISIBLE);
75579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
75679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
75779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
75879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
75979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Gets the data associated with the specified position in the list.
76079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
76179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param position Which data to get
76279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The data associated with the specified position in the list
76379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
76479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public Object getItemAtPosition(int position) {
76579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        T adapter = getAdapter();
76679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return (adapter == null || position < 0) ? null : adapter.getItem(position);
76779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
76879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
76979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public long getItemIdAtPosition(int position) {
77079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        T adapter = getAdapter();
77179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return (adapter == null || position < 0) ? INVALID_ROW_ID : adapter.getItemId(position);
77279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
77379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
77479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
77579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public void setOnClickListener(OnClickListener l) {
77679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        throw new RuntimeException("Don't call setOnClickListener for an AdapterView. "
77779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                + "You probably want setOnItemClickListener instead");
77879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
77979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
78079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
78179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Override to prevent freezing of any views created by the adapter.
78279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
78379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
78479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
78579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        dispatchFreezeSelfOnly(container);
78679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
78779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
78879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
78979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Override to prevent thawing of any views created by the adapter.
79079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
79179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
79279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
79379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        dispatchThawSelfOnly(container);
79479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
79579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
79679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    class AdapterDataSetObserver extends DataSetObserver {
79779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
79879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        private Parcelable mInstanceState = null;
79979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
80079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        @Override
80179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void onChanged() {
80279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mDataChanged = true;
80379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mOldItemCount = mItemCount;
80479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mItemCount = getAdapter().getCount();
80579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
80679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            // Detect the case where a cursor that was previously invalidated has
80779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            // been repopulated with new data.
80879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (AdapterViewICS.this.getAdapter().hasStableIds() && mInstanceState != null
80979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    && mOldItemCount == 0 && mItemCount > 0) {
81079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                AdapterViewICS.this.onRestoreInstanceState(mInstanceState);
81179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mInstanceState = null;
81279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            } else {
81379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                rememberSyncState();
81479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
81579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            checkFocus();
81679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            requestLayout();
81779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
81879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
81979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        @Override
82079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void onInvalidated() {
82179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mDataChanged = true;
82279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
82379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (AdapterViewICS.this.getAdapter().hasStableIds()) {
82479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Remember the current state for the case where our hosting activity is being
82579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // stopped and later restarted
82679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mInstanceState = AdapterViewICS.this.onSaveInstanceState();
82779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
82879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
82979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            // Data is invalid so we should reset our state
83079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mOldItemCount = mItemCount;
83179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mItemCount = 0;
83279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mSelectedPosition = INVALID_POSITION;
83379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mSelectedRowId = INVALID_ROW_ID;
83479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mNextSelectedPosition = INVALID_POSITION;
83579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mNextSelectedRowId = INVALID_ROW_ID;
83679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mNeedSync = false;
83779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
83879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            checkFocus();
83979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            requestLayout();
84079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
84179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
84279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void clearSavedState() {
84379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mInstanceState = null;
84479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
84579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
84679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
84779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
84879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    protected void onDetachedFromWindow() {
84979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        super.onDetachedFromWindow();
85079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        removeCallbacks(mSelectionNotifier);
85179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
85279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
85379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private class SelectionNotifier implements Runnable {
85479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        public void run() {
85579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (mDataChanged) {
85679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Data has changed between when this SelectionNotifier
85779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // was posted and now. We need to wait until the AdapterView
85879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // has been synched to the new data.
85979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (getAdapter() != null) {
86079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    post(this);
86179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
86279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            } else {
86379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                fireOnSelected();
86479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
86579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
86679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
86779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
86879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    void selectionChanged() {
86979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mOnItemSelectedListener != null) {
87079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (mInLayout || mBlockLayoutRequests) {
87179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // If we are in a layout traversal, defer notification
87279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // by posting. This ensures that the view tree is
87379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // in a consistent state and is able to accomodate
87479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // new layout or invalidate requests.
87579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (mSelectionNotifier == null) {
87679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    mSelectionNotifier = new SelectionNotifier();
87779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
87879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                post(mSelectionNotifier);
87979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            } else {
88079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                fireOnSelected();
88179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
88279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
88379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
88479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // we fire selection events here not in View
88579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mSelectedPosition != ListView.INVALID_POSITION && isShown() && !isInTouchMode()) {
88679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
88779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
88879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
88979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
89079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    private void fireOnSelected() {
89179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mOnItemSelectedListener == null)
89279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return;
89379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
89479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int selection = this.getSelectedItemPosition();
89579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (selection >= 0) {
89679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            View v = getSelectedView();
89779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mOnItemSelectedListener.onItemSelected(this, v, selection,
89879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    getAdapter().getItemId(selection));
89979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        } else {
90079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mOnItemSelectedListener.onNothingSelected(this);
90179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
90279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
90379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
90479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
90579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
90679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        View selectedView = getSelectedView();
90779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (selectedView != null && selectedView.getVisibility() == VISIBLE
90879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                && selectedView.dispatchPopulateAccessibilityEvent(event)) {
90979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return true;
91079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
91179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return false;
91279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
91379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
91479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    @Override
91579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    protected boolean canAnimate() {
91679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return super.canAnimate() && mItemCount > 0;
91779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
91879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
91979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    void handleDataChanged() {
92079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        final int count = mItemCount;
92179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        boolean found = false;
92279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
92379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (count > 0) {
92479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
92579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            int newPos;
92679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
92779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            // Find the row we are supposed to sync to
92879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (mNeedSync) {
92979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Update this first, since setNextSelectedPositionInt inspects
93079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // it
93179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mNeedSync = false;
93279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
93379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // See if we can find a position in the new data with the same
93479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // id as the old selection
93579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                newPos = findSyncPosition();
93679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (newPos >= 0) {
93779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    // Verify that new selection is selectable
93879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    int selectablePos = lookForSelectablePosition(newPos, true);
93979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    if (selectablePos == newPos) {
94079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                        // Same row id is selected
94179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                        setNextSelectedPositionInt(newPos);
94279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                        found = true;
94379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    }
94479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
94579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
94679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (!found) {
94779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Try to use the same position if we can't find matching data
94879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                newPos = getSelectedItemPosition();
94979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
95079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Pin position to the available range
95179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (newPos >= count) {
95279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    newPos = count - 1;
95379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
95479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (newPos < 0) {
95579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    newPos = 0;
95679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
95779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
95879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Make sure we select something selectable -- first look down
95979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                int selectablePos = lookForSelectablePosition(newPos, true);
96079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (selectablePos < 0) {
96179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    // Looking down didn't work -- try looking up
96279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    selectablePos = lookForSelectablePosition(newPos, false);
96379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
96479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (selectablePos >= 0) {
96579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    setNextSelectedPositionInt(selectablePos);
96679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    checkSelectionChanged();
96779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    found = true;
96879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
96979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
97079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
97179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (!found) {
97279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            // Nothing is selected
97379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mSelectedPosition = INVALID_POSITION;
97479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mSelectedRowId = INVALID_ROW_ID;
97579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mNextSelectedPosition = INVALID_POSITION;
97679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mNextSelectedRowId = INVALID_ROW_ID;
97779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mNeedSync = false;
97879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            checkSelectionChanged();
97979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
98079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
98179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
98279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    void checkSelectionChanged() {
98379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) {
98479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            selectionChanged();
98579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mOldSelectedPosition = mSelectedPosition;
98679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mOldSelectedRowId = mSelectedRowId;
98779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
98879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
98979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
99079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
99179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Searches the adapter for a position matching mSyncRowId. The search starts at mSyncPosition
99279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * and then alternates between moving up and moving down until 1) we find the right position, or
99379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * 2) we run out of time, or 3) we have looked at every position
99479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
99579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return Position of the row that matches mSyncRowId, or {@link #INVALID_POSITION} if it can't
99679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *         be found
99779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
99879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int findSyncPosition() {
99979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int count = mItemCount;
100079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
100179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (count == 0) {
100279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return INVALID_POSITION;
100379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
100479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
100579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        long idToMatch = mSyncRowId;
100679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int seed = mSyncPosition;
100779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
100879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // If there isn't a selection don't hunt for it
100979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (idToMatch == INVALID_ROW_ID) {
101079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return INVALID_POSITION;
101179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
101279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
101379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Pin seed to reasonable values
101479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        seed = Math.max(0, seed);
101579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        seed = Math.min(count - 1, seed);
101679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
101779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        long endTime = SystemClock.uptimeMillis() + SYNC_MAX_DURATION_MILLIS;
101879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
101979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        long rowId;
102079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
102179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // first position scanned so far
102279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int first = seed;
102379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
102479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // last position scanned so far
102579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        int last = seed;
102679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
102779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // True if we should move down on the next iteration
102879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        boolean next = false;
102979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
103079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // True when we have looked at the first item in the data
103179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        boolean hitFirst;
103279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
103379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // True when we have looked at the last item in the data
103479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        boolean hitLast;
103579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
103679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // Get the item ID locally (instead of getItemIdAtPosition), so
103779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // we need the adapter
103879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        T adapter = getAdapter();
103979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (adapter == null) {
104079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            return INVALID_POSITION;
104179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
104279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
104379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        while (SystemClock.uptimeMillis() <= endTime) {
104479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            rowId = adapter.getItemId(seed);
104579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (rowId == idToMatch) {
104679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Found it!
104779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                return seed;
104879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
104979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
105079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            hitLast = last == count - 1;
105179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            hitFirst = first == 0;
105279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
105379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (hitLast && hitFirst) {
105479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Looked at everything
105579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                break;
105679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
105779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
105879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (hitFirst || (next && !hitLast)) {
105979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Either we hit the top, or we are trying to move down
106079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                last++;
106179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                seed = last;
106279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Try going up next time
106379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                next = false;
106479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            } else if (hitLast || (!next && !hitFirst)) {
106579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Either we hit the bottom, or we are trying to move up
106679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                first--;
106779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                seed = first;
106879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Try going down next time
106979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                next = true;
107079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
107179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
107279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
107379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
107479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return INVALID_POSITION;
107579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
107679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
107779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
107879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Find a position that can be selected (i.e., is not a separator).
107979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
108079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param position The starting position to look at.
108179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param lookDown Whether to look down for other positions.
108279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @return The next selectable position starting at position and then searching either up or
108379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *         down. Returns {@link #INVALID_POSITION} if nothing can be found.
108479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
108579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    int lookForSelectablePosition(int position, boolean lookDown) {
108679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        return position;
108779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
108879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
108979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
109079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Utility to keep mSelectedPosition and mSelectedRowId in sync
109179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param position Our current position
109279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
109379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    void setSelectedPositionInt(int position) {
109479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mSelectedPosition = position;
109579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mSelectedRowId = getItemIdAtPosition(position);
109679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
109779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
109879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
109979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Utility to keep mNextSelectedPosition and mNextSelectedRowId in sync
110079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * @param position Intended value for mSelectedPosition the next time we go
110179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * through layout
110279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
110379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    void setNextSelectedPositionInt(int position) {
110479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mNextSelectedPosition = position;
110579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        mNextSelectedRowId = getItemIdAtPosition(position);
110679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        // If we are trying to sync to the selection, update that too
110779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (mNeedSync && mSyncMode == SYNC_SELECTED_POSITION && position >= 0) {
110879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mSyncPosition = position;
110979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mSyncRowId = mNextSelectedRowId;
111079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
111179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
111279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes
111379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    /**
111479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * Remember enough information to restore the screen state when the data has
111579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     * changed.
111679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     *
111779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes     */
111879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    void rememberSyncState() {
111979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        if (getChildCount() > 0) {
112079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mNeedSync = true;
112179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            mSyncHeight = mLayoutHeight;
112279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            if (mSelectedPosition >= 0) {
112379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Sync the selection state
112479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                View v = getChildAt(mSelectedPosition - mFirstPosition);
112579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mSyncRowId = mNextSelectedRowId;
112679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mSyncPosition = mNextSelectedPosition;
112779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (v != null) {
112879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    mSpecificTop = v.getTop();
112979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
113079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mSyncMode = SYNC_SELECTED_POSITION;
113179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            } else {
113279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                // Sync the based on the offset of the first view
113379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                View v = getChildAt(0);
113479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                T adapter = getAdapter();
113579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (mFirstPosition >= 0 && mFirstPosition < adapter.getCount()) {
113679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    mSyncRowId = adapter.getItemId(mFirstPosition);
113779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                } else {
113879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    mSyncRowId = NO_ID;
113979e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
114079e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mSyncPosition = mFirstPosition;
114179e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                if (v != null) {
114279e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                    mSpecificTop = v.getTop();
114379e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                }
114479e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes                mSyncMode = SYNC_FIRST_POSITION;
114579e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes            }
114679e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes        }
114779e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes    }
114879e7a9ef79920c7daa10c90339db126a4c3c592eChris Banes}