13db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen/*
23db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * Copyright (C) 2010 The Android Open Source Project
33db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen *
43db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * Licensed under the Apache License, Version 2.0 (the "License");
53db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * you may not use this file except in compliance with the License.
63db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * You may obtain a copy of the License at
73db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen *
83db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen *      http://www.apache.org/licenses/LICENSE-2.0
93db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen *
103db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * Unless required by applicable law or agreed to in writing, software
113db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * distributed under the License is distributed on an "AS IS" BASIS,
123db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * See the License for the specific language governing permissions and
143db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * limitations under the License.
153db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen */
163db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
173db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenpackage android.widget;
183db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
19ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohenimport android.animation.AnimatorInflater;
20a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haaseimport android.animation.ObjectAnimator;
213db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.content.Context;
223db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.content.Intent;
233db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.content.res.TypedArray;
243db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.os.Handler;
25b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohenimport android.os.Parcel;
26b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohenimport android.os.Parcelable;
273db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.util.AttributeSet;
28a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohenimport android.view.MotionEvent;
293db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.view.View;
30a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohenimport android.view.ViewConfiguration;
3144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohenimport android.view.ViewGroup;
328a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent;
338a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo;
34a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohenimport android.widget.RemoteViews.OnClickHandler;
353db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
362148d43eb23c702e834c93ae427f822f32d280a2Adam Cohenimport java.util.ArrayList;
372148d43eb23c702e834c93ae427f822f32d280a2Adam Cohenimport java.util.HashMap;
382148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen
393db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen/**
403db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * Base class for a {@link AdapterView} that will perform animations
413db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * when switching between its views.
423db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen *
433db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * @attr ref android.R.styleable#AdapterViewAnimator_inAnimation
443db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * @attr ref android.R.styleable#AdapterViewAnimator_outAnimation
453db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * @attr ref android.R.styleable#AdapterViewAnimator_animateFirstView
461b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen * @attr ref android.R.styleable#AdapterViewAnimator_loopViews
473db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen */
4844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohenpublic abstract class AdapterViewAnimator extends AdapterView<Adapter>
49a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen        implements RemoteViewsAdapter.RemoteAdapterConnectionCallback, Advanceable {
503db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    private static final String TAG = "RemoteViewAnimator";
513db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
5244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
5344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The index of the current child, which appears anywhere from the beginning
5444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * to the end of the current set of children, as specified by {@link #mActiveOffset}
5544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
563db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    int mWhichChild = 0;
5744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
5844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
5916c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung     * The index of the child to restore after the asynchronous connection from the
6016c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung     * RemoteViewsAdapter has been.
6116c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung     */
6216c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung    private int mRestoreWhichChild = -1;
6316c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung
6416c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung    /**
6544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Whether or not the first view(s) should be animated in
6644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
673db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    boolean mAnimateFirstTime = true;
683db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
6944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
7044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *  Represents where the in the current window of
7144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *  views the current <code>mDisplayedChild</code> sits
7244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
7344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    int mActiveOffset = 0;
7444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
7544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
7644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The number of views that the {@link AdapterViewAnimator} keeps as children at any
7744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * given time (not counting views that are pending removal, see {@link #mPreviousViews}).
7844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
7996d8d56302da81b24333b204e6d7f15064538036Adam Cohen    int mMaxNumActiveViews = 1;
8044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
8144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
821b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen     * Map of the children of the {@link AdapterViewAnimator}.
8344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
84d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen    HashMap<Integer, ViewAndMetaData> mViewsMap = new HashMap<Integer, ViewAndMetaData>();
8544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
8644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
8744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * List of views pending removal from the {@link AdapterViewAnimator}
8844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
891b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen    ArrayList<Integer> mPreviousViews;
9044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
9144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
9244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The index, relative to the adapter, of the beginning of the window of views
9344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
9444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    int mCurrentWindowStart = 0;
9544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
9644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
9744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The index, relative to the adapter, of the end of the window of views
9844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
9944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    int mCurrentWindowEnd = -1;
10044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
10144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
10244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The same as {@link #mCurrentWindowStart}, except when the we have bounded
10344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * {@link #mCurrentWindowStart} to be non-negative
10444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
10544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    int mCurrentWindowStartUnbounded = 0;
10644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
10744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
10844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Listens for data changes from the adapter
10944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
1103db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    AdapterDataSetObserver mDataSetObserver;
1113db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
11244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
11344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The {@link Adapter} for this {@link AdapterViewAnimator}
11444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
11544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    Adapter mAdapter;
11644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
11744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
11844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The {@link RemoteViewsAdapter} for this {@link AdapterViewAnimator}
11944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
12044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    RemoteViewsAdapter mRemoteViewsAdapter;
12144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
12244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
1232148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen     * The remote adapter containing the data to be displayed by this view to be set
1242148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen     */
1252148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen    boolean mDeferNotifyDataSetChanged = false;
1262148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen
1272148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen    /**
12844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Specifies whether this is the first time the animator is showing views
12944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
13044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    boolean mFirstTime = true;
1313db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
13244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
133b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen     * Specifies if the animator should wrap from 0 to the end and vice versa
134b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen     * or have hard boundaries at the beginning and end
135b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen     */
1361b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen    boolean mLoopViews = true;
137b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
138b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    /**
139839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen     * The width and height of some child, used as a size reference in-case our
140839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen     * dimensions are unspecified by the parent.
141839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen     */
142839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    int mReferenceChildWidth = -1;
143839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    int mReferenceChildHeight = -1;
144839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
145839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    /**
146ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen     * In and out animations.
14744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
1482794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    ObjectAnimator mInAnimation;
1492794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    ObjectAnimator mOutAnimation;
150ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen
151a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    /**
152a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen     * Current touch state.
153a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen     */
154a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    private int mTouchMode = TOUCH_MODE_NONE;
155a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen
156a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    /**
157a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen     * Private touch states.
158a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen     */
159a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    static final int TOUCH_MODE_NONE = 0;
160a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    static final int TOUCH_MODE_DOWN_IN_CURRENT_VIEW = 1;
161a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    static final int TOUCH_MODE_HANDLED = 2;
162a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen
163a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    private Runnable mPendingCheckForTap;
164a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen
165ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen    private static final int DEFAULT_ANIMATION_DURATION = 200;
166ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen
1673db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public AdapterViewAnimator(Context context) {
16826f072c3ee4f2baecf4fd3f8ed829ed709055cf4Adam Cohen        this(context, null);
1693db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
1703db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
1713db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public AdapterViewAnimator(Context context, AttributeSet attrs) {
17226f072c3ee4f2baecf4fd3f8ed829ed709055cf4Adam Cohen        this(context, attrs, 0);
17326f072c3ee4f2baecf4fd3f8ed829ed709055cf4Adam Cohen    }
17426f072c3ee4f2baecf4fd3f8ed829ed709055cf4Adam Cohen
17526f072c3ee4f2baecf4fd3f8ed829ed709055cf4Adam Cohen    public AdapterViewAnimator(Context context, AttributeSet attrs, int defStyleAttr) {
176617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        this(context, attrs, defStyleAttr, 0);
177617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    }
178617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette
179617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette    public AdapterViewAnimator(
180617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
181617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        super(context, attrs, defStyleAttr, defStyleRes);
1823db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
183617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette        final TypedArray a = context.obtainStyledAttributes(attrs,
184617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette                com.android.internal.R.styleable.AdapterViewAnimator, defStyleAttr, defStyleRes);
18544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        int resource = a.getResourceId(
1861b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                com.android.internal.R.styleable.AdapterViewAnimator_inAnimation, 0);
1873db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (resource > 0) {
1883db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            setInAnimation(context, resource);
189ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen        } else {
190ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen            setInAnimation(getDefaultInAnimation());
1913db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
1923db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
1931b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        resource = a.getResourceId(com.android.internal.R.styleable.AdapterViewAnimator_outAnimation, 0);
1943db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (resource > 0) {
1953db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            setOutAnimation(context, resource);
196ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen        } else {
197ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen            setOutAnimation(getDefaultOutAnimation());
1983db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
1993db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
20044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        boolean flag = a.getBoolean(
2011b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                com.android.internal.R.styleable.AdapterViewAnimator_animateFirstView, true);
2023db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        setAnimateFirstView(flag);
2033db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
2041b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        mLoopViews = a.getBoolean(
2051b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                com.android.internal.R.styleable.AdapterViewAnimator_loopViews, false);
2061b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen
2073db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        a.recycle();
2083db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
2095b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy        initViewAnimator();
2103db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
2113db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
2123db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
2133db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Initialize this {@link AdapterViewAnimator}
2143db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
2155b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy    private void initViewAnimator() {
2161b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        mPreviousViews = new ArrayList<Integer>();
21744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    }
21844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
219d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen    class ViewAndMetaData {
2201b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        View view;
221d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen        int relativeIndex;
222d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen        int adapterPosition;
223d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen        long itemId;
224d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen
225d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen        ViewAndMetaData(View view, int relativeIndex, int adapterPosition, long itemId) {
226d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen            this.view = view;
227d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen            this.relativeIndex = relativeIndex;
228d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen            this.adapterPosition = adapterPosition;
229d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen            this.itemId = itemId;
230d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen        }
2311b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen    }
2321b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen
23344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
23444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * This method is used by subclasses to configure the animator to display the
23544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * desired number of views, and specify the offset
23644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *
23744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param numVisibleViews The number of views the animator keeps in the {@link ViewGroup}
2385b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy     * @param activeOffset This parameter specifies where the current index ({@link #mWhichChild})
23944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *        sits within the window. For example if activeOffset is 1, and numVisibleViews is 3,
2405b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy     *        and {@link #setDisplayedChild(int)} is called with 10, then the effective window will
2415b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy     *        be the indexes 9, 10, and 11. In the same example, if activeOffset were 0, then the
24244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *        window would instead contain indexes 10, 11 and 12.
243b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen     * @param shouldLoop If the animator is show view 0, and setPrevious() is called, do we
244b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen     *        we loop back to the end, or do we do nothing
24544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
2461b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen     void configureViewAnimator(int numVisibleViews, int activeOffset) {
24744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        if (activeOffset > numVisibleViews - 1) {
24844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            // Throw an exception here.
24944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
25096d8d56302da81b24333b204e6d7f15064538036Adam Cohen        mMaxNumActiveViews = numVisibleViews;
25144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mActiveOffset = activeOffset;
25244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mPreviousViews.clear();
2531b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        mViewsMap.clear();
25444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        removeAllViewsInLayout();
25544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mCurrentWindowStart = 0;
25644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mCurrentWindowEnd = -1;
25744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    }
25844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
25944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
26044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * This class should be overridden by subclasses to customize view transitions within
26144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * the set of visible views
26244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *
26344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param fromIndex The relative index within the window that the view was in, -1 if it wasn't
26444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *        in the window
26544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param toIndex The relative index within the window that the view is going to, -1 if it is
26644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *        being removed
26744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param view The view that is being animated
26844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
26978db1aa9118edd71c2da28a2c23a0d875d1a707aAdam Cohen    void transformViewForTransition(int fromIndex, int toIndex, View view, boolean animate) {
27044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        if (fromIndex == -1) {
271ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen            mInAnimation.setTarget(view);
272ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen            mInAnimation.start();
27344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        } else if (toIndex == -1) {
274ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen            mOutAnimation.setTarget(view);
275ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen            mOutAnimation.start();
27644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
2773db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
2783db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
2792794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    ObjectAnimator getDefaultInAnimation() {
2802794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        ObjectAnimator anim = ObjectAnimator.ofFloat(null, "alpha", 0.0f, 1.0f);
2812794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        anim.setDuration(DEFAULT_ANIMATION_DURATION);
2822794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        return anim;
283ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen    }
284ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen
2852794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    ObjectAnimator getDefaultOutAnimation() {
2862794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        ObjectAnimator anim = ObjectAnimator.ofFloat(null, "alpha", 1.0f, 0.0f);
2872794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        anim.setDuration(DEFAULT_ANIMATION_DURATION);
2882794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        return anim;
289ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen    }
290ef52176f1244a5bb98d82a0c8c7f4351edec17a1Adam Cohen
2913db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
2923db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Sets which child view will be displayed.
2933db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
2943db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param whichChild the index of the child view to display
2953db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
2960b96a57c851af2f66e3bc738035478efb3c1957eAdam Cohen    @android.view.RemotableViewMethod
2973db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setDisplayedChild(int whichChild) {
29853838d265e36fb50341af168f5a91c3341c3cfc3Adam Cohen        setDisplayedChild(whichChild, true);
29953838d265e36fb50341af168f5a91c3341c3cfc3Adam Cohen    }
30053838d265e36fb50341af168f5a91c3341c3cfc3Adam Cohen
30153838d265e36fb50341af168f5a91c3341c3cfc3Adam Cohen    private void setDisplayedChild(int whichChild, boolean animate) {
3023db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (mAdapter != null) {
3033db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            mWhichChild = whichChild;
30496d8d56302da81b24333b204e6d7f15064538036Adam Cohen            if (whichChild >= getWindowSize()) {
30596d8d56302da81b24333b204e6d7f15064538036Adam Cohen                mWhichChild = mLoopViews ? 0 : getWindowSize() - 1;
3063db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            } else if (whichChild < 0) {
30796d8d56302da81b24333b204e6d7f15064538036Adam Cohen                mWhichChild = mLoopViews ? getWindowSize() - 1 : 0;
3083db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            }
3093db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
3103db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            boolean hasFocus = getFocusedChild() != null;
3113db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            // This will clear old focus if we had it
31253838d265e36fb50341af168f5a91c3341c3cfc3Adam Cohen            showOnly(mWhichChild, animate);
3133db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            if (hasFocus) {
3143db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen                // Try to retake focus if we had it
3153db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen                requestFocus(FOCUS_FORWARD);
3163db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            }
3173db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
3183db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
3193db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
3203db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
32144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * To be overridden by subclasses. This method applies a view / index specific
32244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * transform to the child view.
32344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *
32444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param child
32544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param relativeIndex
32644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
32744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    void applyTransformForChildAtIndex(View child, int relativeIndex) {
32844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    }
32944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
33044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
3313db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Returns the index of the currently displayed child view.
3323db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
3333db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public int getDisplayedChild() {
3343db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return mWhichChild;
3353db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
3363db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
3373db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
3383db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Manually shows the next child.
3393db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
3403db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void showNext() {
3413db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        setDisplayedChild(mWhichChild + 1);
3423db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
3433db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
3443db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
3453db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Manually shows the previous child.
3463db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
3473db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void showPrevious() {
3483db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        setDisplayedChild(mWhichChild - 1);
3493db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
3503db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
35196d8d56302da81b24333b204e6d7f15064538036Adam Cohen    int modulo(int pos, int size) {
3523042944c6ec68210ba1746540b53789e70d15ef4Adam Cohen        if (size > 0) {
3533042944c6ec68210ba1746540b53789e70d15ef4Adam Cohen            return (size + (pos % size)) % size;
3543042944c6ec68210ba1746540b53789e70d15ef4Adam Cohen        } else {
3553042944c6ec68210ba1746540b53789e70d15ef4Adam Cohen            return 0;
3563042944c6ec68210ba1746540b53789e70d15ef4Adam Cohen        }
3573db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
3583db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
35944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
36044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Get the view at this index relative to the current window's start
36144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *
36244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param relativeIndex Position relative to the current window's start
36344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @return View at this index, null if the index is outside the bounds
36444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
36544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    View getViewAtRelativeIndex(int relativeIndex) {
36696d8d56302da81b24333b204e6d7f15064538036Adam Cohen        if (relativeIndex >= 0 && relativeIndex <= getNumActiveViews() - 1 && mAdapter != null) {
36796d8d56302da81b24333b204e6d7f15064538036Adam Cohen            int i = modulo(mCurrentWindowStartUnbounded + relativeIndex, getWindowSize());
3686f279627cfa3286e6901a8dc2ed8361576ce226dAdam Cohen            if (mViewsMap.get(i) != null) {
3696f279627cfa3286e6901a8dc2ed8361576ce226dAdam Cohen                return mViewsMap.get(i).view;
3706f279627cfa3286e6901a8dc2ed8361576ce226dAdam Cohen            }
37144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
37244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        return null;
37344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    }
3743db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
37596d8d56302da81b24333b204e6d7f15064538036Adam Cohen    int getNumActiveViews() {
37696d8d56302da81b24333b204e6d7f15064538036Adam Cohen        if (mAdapter != null) {
377ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen            return Math.min(getCount() + 1, mMaxNumActiveViews);
37896d8d56302da81b24333b204e6d7f15064538036Adam Cohen        } else {
37996d8d56302da81b24333b204e6d7f15064538036Adam Cohen            return mMaxNumActiveViews;
38096d8d56302da81b24333b204e6d7f15064538036Adam Cohen        }
38196d8d56302da81b24333b204e6d7f15064538036Adam Cohen    }
38296d8d56302da81b24333b204e6d7f15064538036Adam Cohen
38396d8d56302da81b24333b204e6d7f15064538036Adam Cohen    int getWindowSize() {
38496d8d56302da81b24333b204e6d7f15064538036Adam Cohen        if (mAdapter != null) {
385ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen            int adapterCount = getCount();
38696d8d56302da81b24333b204e6d7f15064538036Adam Cohen            if (adapterCount <= getNumActiveViews() && mLoopViews) {
38796d8d56302da81b24333b204e6d7f15064538036Adam Cohen                return adapterCount*mMaxNumActiveViews;
38896d8d56302da81b24333b204e6d7f15064538036Adam Cohen            } else {
38996d8d56302da81b24333b204e6d7f15064538036Adam Cohen                return adapterCount;
39096d8d56302da81b24333b204e6d7f15064538036Adam Cohen            }
39196d8d56302da81b24333b204e6d7f15064538036Adam Cohen        } else {
39296d8d56302da81b24333b204e6d7f15064538036Adam Cohen            return 0;
39396d8d56302da81b24333b204e6d7f15064538036Adam Cohen        }
39496d8d56302da81b24333b204e6d7f15064538036Adam Cohen    }
39596d8d56302da81b24333b204e6d7f15064538036Adam Cohen
396d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen    private ViewAndMetaData getMetaDataForChild(View child) {
397d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen        for (ViewAndMetaData vm: mViewsMap.values()) {
398d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen            if (vm.view == child) {
399d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                return vm;
400d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen            }
401d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen        }
402d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen        return null;
403d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen     }
404d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen
4059b073948cfb84c0dd04f8a94ee1f7f263f027c83Adam Cohen    LayoutParams createOrReuseLayoutParams(View v) {
4065b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy        final ViewGroup.LayoutParams currentLp = v.getLayoutParams();
4079b073948cfb84c0dd04f8a94ee1f7f263f027c83Adam Cohen        if (currentLp instanceof ViewGroup.LayoutParams) {
408b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            LayoutParams lp = (LayoutParams) currentLp;
409b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            return lp;
41044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
4119b073948cfb84c0dd04f8a94ee1f7f263f027c83Adam Cohen        return new ViewGroup.LayoutParams(0, 0);
41244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    }
4133db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
4146364f2bbe5254b4274f3feffc48f4259eacc205eWinson Chung    void refreshChildren() {
415a9238c89a43500ed0bcdeaee182be08ff991c627Adam Cohen        if (mAdapter == null) return;
416bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen        for (int i = mCurrentWindowStart; i <= mCurrentWindowEnd; i++) {
417a9238c89a43500ed0bcdeaee182be08ff991c627Adam Cohen            int index = modulo(i, getWindowSize());
418bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen
419ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen            int adapterCount = getCount();
420bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen            // get the fresh child from the adapter
421ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen            final View updatedChild = mAdapter.getView(modulo(i, adapterCount), null, this);
422bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen
4234213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov            if (updatedChild.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
4244213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov                updatedChild.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
4254213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov            }
4264213804541a8b05cd0587b138a2fd9a3b7fd9350Svetoslav Ganov
4271b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen            if (mViewsMap.containsKey(index)) {
428ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                final FrameLayout fl = (FrameLayout) mViewsMap.get(index).view;
429bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                // add the new child to the frame, if it exists
430bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                if (updatedChild != null) {
431ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                    // flush out the old child
432ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                    fl.removeAllViewsInLayout();
433bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    fl.addView(updatedChild);
434bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                }
435bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen            }
436bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen        }
437bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen    }
438bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen
439dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen    /**
440dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen     * This method can be overridden so that subclasses can provide a custom frame in which their
441dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen     * children can live. For example, StackView adds padding to its childrens' frames so as to
442dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen     * accomodate for the highlight effect.
443dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen     *
444dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen     * @return The FrameLayout into which children can be placed.
445dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen     */
446dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen    FrameLayout getFrameForChild() {
447dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen        return new FrameLayout(mContext);
448dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen    }
449dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen
450ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen    /**
451ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen     * Shows only the specified child. The other displays Views exit the screen,
452ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen     * optionally with the with the {@link #getOutAnimation() out animation} and
453ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen     * the specified child enters the screen, optionally with the
454ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen     * {@link #getInAnimation() in animation}.
455ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen     *
456ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen     * @param childIndex The index of the child to be shown.
457ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen     * @param animate Whether or not to use the in and out animations, defaults
458ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen     *            to true.
459ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen     */
460ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen    void showOnly(int childIndex, boolean animate) {
46144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        if (mAdapter == null) return;
462ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen        final int adapterCount = getCount();
4633042944c6ec68210ba1746540b53789e70d15ef4Adam Cohen        if (adapterCount == 0) return;
4643db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
46544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        for (int i = 0; i < mPreviousViews.size(); i++) {
4661b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen            View viewToRemove = mViewsMap.get(mPreviousViews.get(i)).view;
4671b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen            mViewsMap.remove(mPreviousViews.get(i));
46844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            viewToRemove.clearAnimation();
4693d07af03421f4727ef7e97c5c19e6ade50b19060Adam Cohen            if (viewToRemove instanceof ViewGroup) {
4703d07af03421f4727ef7e97c5c19e6ade50b19060Adam Cohen                ViewGroup vg = (ViewGroup) viewToRemove;
4713d07af03421f4727ef7e97c5c19e6ade50b19060Adam Cohen                vg.removeAllViewsInLayout();
4723d07af03421f4727ef7e97c5c19e6ade50b19060Adam Cohen            }
47344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            // applyTransformForChildAtIndex here just allows for any cleanup
47444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            // associated with this view that may need to be done by a subclass
47544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            applyTransformForChildAtIndex(viewToRemove, -1);
4763d07af03421f4727ef7e97c5c19e6ade50b19060Adam Cohen
47744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            removeViewInLayout(viewToRemove);
47844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
47944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mPreviousViews.clear();
48044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        int newWindowStartUnbounded = childIndex - mActiveOffset;
48196d8d56302da81b24333b204e6d7f15064538036Adam Cohen        int newWindowEndUnbounded = newWindowStartUnbounded + getNumActiveViews() - 1;
48244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        int newWindowStart = Math.max(0, newWindowStartUnbounded);
4831b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        int newWindowEnd = Math.min(adapterCount - 1, newWindowEndUnbounded);
48444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
4851b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        if (mLoopViews) {
4861b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen            newWindowStart = newWindowStartUnbounded;
4871b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen            newWindowEnd = newWindowEndUnbounded;
4881b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        }
48996d8d56302da81b24333b204e6d7f15064538036Adam Cohen        int rangeStart = modulo(newWindowStart, getWindowSize());
49096d8d56302da81b24333b204e6d7f15064538036Adam Cohen        int rangeEnd = modulo(newWindowEnd, getWindowSize());
4911b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen
4921b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        boolean wrap = false;
4931b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        if (rangeStart > rangeEnd) {
4941b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen            wrap = true;
4951b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        }
4961b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen
4971b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        // This section clears out any items that are in our active views list
49844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        // but are outside the effective bounds of our window (this is becomes an issue
49944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        // at the extremities of the list, eg. where newWindowStartUnbounded < 0 or
500ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen        // newWindowEndUnbounded > adapterCount - 1
5011b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen        for (Integer index : mViewsMap.keySet()) {
5021b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen            boolean remove = false;
5031b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen            if (!wrap && (index < rangeStart || index > rangeEnd)) {
5041b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                remove = true;
5051b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen            } else if (wrap && (index > rangeEnd && index < rangeStart)) {
5061b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                remove = true;
5071b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen            }
5081b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen
5091b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen            if (remove) {
5101b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                View previousView = mViewsMap.get(index).view;
511d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                int oldRelativeIndex = mViewsMap.get(index).relativeIndex;
5121b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen
5131b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                mPreviousViews.add(index);
51478db1aa9118edd71c2da28a2c23a0d875d1a707aAdam Cohen                transformViewForTransition(oldRelativeIndex, -1, previousView, animate);
5153db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            }
51644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
5173db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
51844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        // If the window has changed
51996d8d56302da81b24333b204e6d7f15064538036Adam Cohen        if (!(newWindowStart == mCurrentWindowStart && newWindowEnd == mCurrentWindowEnd &&
52096d8d56302da81b24333b204e6d7f15064538036Adam Cohen              newWindowStartUnbounded == mCurrentWindowStartUnbounded)) {
52144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            // Run through the indices in the new range
52244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            for (int i = newWindowStart; i <= newWindowEnd; i++) {
52344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
52496d8d56302da81b24333b204e6d7f15064538036Adam Cohen                int index = modulo(i, getWindowSize());
5251b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                int oldRelativeIndex;
5261b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                if (mViewsMap.containsKey(index)) {
527d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                    oldRelativeIndex = mViewsMap.get(index).relativeIndex;
5281b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                } else {
5291b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                    oldRelativeIndex = -1;
5301b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                }
53144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                int newRelativeIndex = i - newWindowStartUnbounded;
53244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
53344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                // If this item is in the current window, great, we just need to apply
53444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                // the transform for it's new relative position in the window, and animate
53544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                // between it's current and new relative positions
5361b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                boolean inOldRange = mViewsMap.containsKey(index) && !mPreviousViews.contains(index);
5371b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen
5381b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                if (inOldRange) {
5391b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                    View view = mViewsMap.get(index).view;
540d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                    mViewsMap.get(index).relativeIndex = newRelativeIndex;
54144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    applyTransformForChildAtIndex(view, newRelativeIndex);
54278db1aa9118edd71c2da28a2c23a0d875d1a707aAdam Cohen                    transformViewForTransition(oldRelativeIndex, newRelativeIndex, view, animate);
54344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
5441b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                // Otherwise this view is new to the window
54544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                } else {
5461b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                    // Get the new view from the adapter, add it and apply any transform / animation
547d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                    final int adapterPosition = modulo(i, adapterCount);
548d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                    View newView = mAdapter.getView(adapterPosition, null, this);
549d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                    long itemId = mAdapter.getItemId(adapterPosition);
550bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen
551bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    // We wrap the new view in a FrameLayout so as to respect the contract
552bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    // with the adapter, that is, that we don't modify this view directly
553dfcdddd7c408dddb22fb0867e4799d4c29d2f55fAdam Cohen                    FrameLayout fl = getFrameForChild();
554bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen
555bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    // If the view from the adapter is null, we still keep an empty frame in place
55644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    if (newView != null) {
557bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                       fl.addView(newView);
55844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    }
559d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                    mViewsMap.put(index, new ViewAndMetaData(fl, newRelativeIndex,
560d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                            adapterPosition, itemId));
561bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    addChild(fl);
562bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    applyTransformForChildAtIndex(fl, newRelativeIndex);
56378db1aa9118edd71c2da28a2c23a0d875d1a707aAdam Cohen                    transformViewForTransition(-1, newRelativeIndex, fl, animate);
5643db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen                }
5651b065cd1401253f999caa5d0ac12909407cef00eAdam Cohen                mViewsMap.get(index).view.bringToFront();
5663db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            }
56744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            mCurrentWindowStart = newWindowStart;
56844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            mCurrentWindowEnd = newWindowEnd;
56944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            mCurrentWindowStartUnbounded = newWindowStartUnbounded;
570b967392e0170af8cfd8053fd43fcdf8c46f703e9Adam Cohen            if (mRemoteViewsAdapter != null) {
571d0c735fccc904366ded657263c33bb15475a1123Adam Cohen                int adapterStart = modulo(mCurrentWindowStart, adapterCount);
572d0c735fccc904366ded657263c33bb15475a1123Adam Cohen                int adapterEnd = modulo(mCurrentWindowEnd, adapterCount);
573d0c735fccc904366ded657263c33bb15475a1123Adam Cohen                mRemoteViewsAdapter.setVisibleRangeHint(adapterStart, adapterEnd);
574b967392e0170af8cfd8053fd43fcdf8c46f703e9Adam Cohen            }
57544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
576ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen        requestLayout();
577ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen        invalidate();
5783db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
5793db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
580839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    private void addChild(View child) {
581839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        addViewInLayout(child, -1, createOrReuseLayoutParams(child));
582839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
583839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // This code is used to obtain a reference width and height of a child in case we need
584839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // to decide our own size. TODO: Do we want to update the size of the child that we're
585839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // using for reference size? If so, when?
586839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        if (mReferenceChildWidth == -1 || mReferenceChildHeight == -1) {
587839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            int measureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
588839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            child.measure(measureSpec, measureSpec);
589839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            mReferenceChildWidth = child.getMeasuredWidth();
590839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            mReferenceChildHeight = child.getMeasuredHeight();
591839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        }
592839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    }
593839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
594a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    void showTapFeedback(View v) {
595a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        v.setPressed(true);
596a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    }
597a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen
598a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    void hideTapFeedback(View v) {
599a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        v.setPressed(false);
600a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    }
601a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen
602a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    void cancelHandleClick() {
603a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        View v = getCurrentView();
604a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        if (v != null) {
605a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen            hideTapFeedback(v);
606a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        }
607a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        mTouchMode = TOUCH_MODE_NONE;
608a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    }
609a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen
610a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    final class CheckForTap implements Runnable {
611a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        public void run() {
612a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen            if (mTouchMode == TOUCH_MODE_DOWN_IN_CURRENT_VIEW) {
613a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                View v = getCurrentView();
614a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                showTapFeedback(v);
615a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen            }
616a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        }
617a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    }
618a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen
619a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    @Override
620a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    public boolean onTouchEvent(MotionEvent ev) {
621a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        int action = ev.getAction();
622a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        boolean handled = false;
623a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        switch (action) {
624a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen            case MotionEvent.ACTION_DOWN: {
625a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                View v = getCurrentView();
626a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                if (v != null) {
627a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                    if (isTransformedTouchPointInView(ev.getX(), ev.getY(), v, null)) {
628a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                        if (mPendingCheckForTap == null) {
629a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                            mPendingCheckForTap = new CheckForTap();
630a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                        }
631a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                        mTouchMode = TOUCH_MODE_DOWN_IN_CURRENT_VIEW;
632a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
633a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                    }
634a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                }
635a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                break;
636a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen            }
637a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen            case MotionEvent.ACTION_MOVE: break;
638a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen            case MotionEvent.ACTION_POINTER_UP: break;
639a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen            case MotionEvent.ACTION_UP: {
640a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                if (mTouchMode == TOUCH_MODE_DOWN_IN_CURRENT_VIEW) {
641a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                    final View v = getCurrentView();
642d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                    final ViewAndMetaData viewData = getMetaDataForChild(v);
643a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                    if (v != null) {
644a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                        if (isTransformedTouchPointInView(ev.getX(), ev.getY(), v, null)) {
645a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                            final Handler handler = getHandler();
646a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                            if (handler != null) {
647a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                                handler.removeCallbacks(mPendingCheckForTap);
648a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                            }
649a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                            showTapFeedback(v);
650a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                            postDelayed(new Runnable() {
651a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                                public void run() {
652a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                                    hideTapFeedback(v);
653a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                                    post(new Runnable() {
654a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                                        public void run() {
655d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                                            if (viewData != null) {
656d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                                                performItemClick(v, viewData.adapterPosition,
657d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                                                        viewData.itemId);
658d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                                            } else {
659d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                                                performItemClick(v, 0, 0);
660d38a0cee2074fcf8005fc0d746aad282941a39b8Adam Cohen                                            }
661a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                                        }
662a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                                    });
663a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                                }
664a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                            }, ViewConfiguration.getPressedStateDuration());
665a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                            handled = true;
666a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                        }
667a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                    }
668a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                }
669a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                mTouchMode = TOUCH_MODE_NONE;
670a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                break;
671a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen            }
672a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen            case MotionEvent.ACTION_CANCEL: {
673a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                View v = getCurrentView();
674a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                if (v != null) {
675a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                    hideTapFeedback(v);
676a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                }
677a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen                mTouchMode = TOUCH_MODE_NONE;
678a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen            }
679a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        }
680a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen        return handled;
681a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen    }
682a32edd4b4c894f4fb3d9fd7e9d5b80321df79e20Adam Cohen
683839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    private void measureChildren() {
684839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        final int count = getChildCount();
685189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn        final int childWidth = getMeasuredWidth() - mPaddingLeft - mPaddingRight;
686189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn        final int childHeight = getMeasuredHeight() - mPaddingTop - mPaddingBottom;
687839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
688839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        for (int i = 0; i < count; i++) {
689839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            final View child = getChildAt(i);
690839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
691839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen                    MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
692839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        }
693839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    }
694839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
695839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    @Override
696839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
697839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
698839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
699839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
700839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
701839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
702839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        boolean haveChildRefSize = (mReferenceChildWidth != -1 && mReferenceChildHeight != -1);
703839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
704839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // We need to deal with the case where our parent hasn't told us how
705839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // big we should be. In this case we try to use the desired size of the first
706839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // child added.
707839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        if (heightSpecMode == MeasureSpec.UNSPECIFIED) {
708839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            heightSpecSize = haveChildRefSize ? mReferenceChildHeight + mPaddingTop +
709839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen                    mPaddingBottom : 0;
710839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
711189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn            if (haveChildRefSize) {
712189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                int height = mReferenceChildHeight + mPaddingTop + mPaddingBottom;
713189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                if (height > heightSpecSize) {
714189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                    heightSpecSize |= MEASURED_STATE_TOO_SMALL;
715189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                } else {
716189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                    heightSpecSize = height;
717189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                }
718189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn            }
719839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        }
720839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
721839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        if (widthSpecMode == MeasureSpec.UNSPECIFIED) {
722839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            widthSpecSize = haveChildRefSize ? mReferenceChildWidth + mPaddingLeft +
723839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen                    mPaddingRight : 0;
724839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
725189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn            if (haveChildRefSize) {
726189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                int width = mReferenceChildWidth + mPaddingLeft + mPaddingRight;
727189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                if (width > widthSpecSize) {
728189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                    widthSpecSize |= MEASURED_STATE_TOO_SMALL;
729189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                } else {
730189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                    widthSpecSize = width;
731189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn                }
732189ee18d6c6483ad63cc864267328259e2e00b95Dianne Hackborn            }
733839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        }
734839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
735839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        setMeasuredDimension(widthSpecSize, heightSpecSize);
736839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        measureChildren();
737839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    }
738839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
739ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen    void checkForAndHandleDataChanged() {
7403db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        boolean dataChanged = mDataChanged;
7413db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (dataChanged) {
742ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen            post(new Runnable() {
743ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                public void run() {
744ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                    handleDataChanged();
745ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                    // if the data changes, mWhichChild might be out of the bounds of the adapter
746ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                    // in this case, we reset mWhichChild to the beginning
747ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                    if (mWhichChild >= getWindowSize()) {
748ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                        mWhichChild = 0;
7493db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
75078db1aa9118edd71c2da28a2c23a0d875d1a707aAdam Cohen                        showOnly(mWhichChild, false);
751e86ff4d56145d875c13a1637833f9f55d79febc9Adam Cohen                    } else if (mOldItemCount != getCount()) {
75278db1aa9118edd71c2da28a2c23a0d875d1a707aAdam Cohen                        showOnly(mWhichChild, false);
753ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                    }
754ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                    refreshChildren();
755ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                    requestLayout();
756ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen                }
757ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen            });
7583db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
759ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen        mDataChanged = false;
760ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen    }
761ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen
762ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen    @Override
763ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
764ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen        checkForAndHandleDataChanged();
7653db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7663db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        final int childCount = getChildCount();
7673db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        for (int i = 0; i < childCount; i++) {
7683db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            final View child = getChildAt(i);
7693db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7703db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            int childRight = mPaddingLeft + child.getMeasuredWidth();
7713db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            int childBottom = mPaddingTop + child.getMeasuredHeight();
7723db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
773839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            child.layout(mPaddingLeft, mPaddingTop, childRight, childBottom);
7743db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
7753db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
7763db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
777b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    static class SavedState extends BaseSavedState {
778b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        int whichChild;
779b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
780b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        /**
781b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen         * Constructor called from {@link AdapterViewAnimator#onSaveInstanceState()}
782b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen         */
783b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        SavedState(Parcelable superState, int whichChild) {
784b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            super(superState);
785b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            this.whichChild = whichChild;
786b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        }
787b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
788b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        /**
789b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen         * Constructor called from {@link #CREATOR}
790b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen         */
791b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        private SavedState(Parcel in) {
792b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            super(in);
7933ec9a45c36d3ca5ffbc6e85bbeb497b065e14155Winson Chung            this.whichChild = in.readInt();
794b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        }
795b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
796b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        @Override
797b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        public void writeToParcel(Parcel out, int flags) {
798b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            super.writeToParcel(out, flags);
7993ec9a45c36d3ca5ffbc6e85bbeb497b065e14155Winson Chung            out.writeInt(this.whichChild);
800b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        }
801b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
802b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        @Override
803b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        public String toString() {
8043ec9a45c36d3ca5ffbc6e85bbeb497b065e14155Winson Chung            return "AdapterViewAnimator.SavedState{ whichChild = " + this.whichChild + " }";
805b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        }
806b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
807b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        public static final Parcelable.Creator<SavedState> CREATOR
808b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen                = new Parcelable.Creator<SavedState>() {
809b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            public SavedState createFromParcel(Parcel in) {
810b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen                return new SavedState(in);
811b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            }
812b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
813b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            public SavedState[] newArray(int size) {
814b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen                return new SavedState[size];
815b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            }
816b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        };
817b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    }
818b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
819b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    @Override
820b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    public Parcelable onSaveInstanceState() {
821b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        Parcelable superState = super.onSaveInstanceState();
822335c3b681bf1c118d9bf22d1a508c87173632ec6Adam Cohen        if (mRemoteViewsAdapter != null) {
823335c3b681bf1c118d9bf22d1a508c87173632ec6Adam Cohen            mRemoteViewsAdapter.saveRemoteViewsCache();
824335c3b681bf1c118d9bf22d1a508c87173632ec6Adam Cohen        }
825b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        return new SavedState(superState, mWhichChild);
826b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    }
827b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
828b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    @Override
829b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    public void onRestoreInstanceState(Parcelable state) {
830b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        SavedState ss = (SavedState) state;
831b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        super.onRestoreInstanceState(ss.getSuperState());
832b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
833b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        // Here we set mWhichChild in addition to setDisplayedChild
834b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        // We do the former in case mAdapter is null, and hence setDisplayedChild won't
835b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        // set mWhichChild
836b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        mWhichChild = ss.whichChild;
83769d66e00136f67332c992326a7b2eb334eeb32a2Adam Cohen
83816c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        // When using RemoteAdapters, the async connection process can lead to
83916c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        // onRestoreInstanceState to be called before setAdapter(), so we need to save the previous
84016c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        // values to restore the list position after we connect, and can skip setting the displayed
84116c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        // child until then.
84216c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        if (mRemoteViewsAdapter != null && mAdapter == null) {
84316c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            mRestoreWhichChild = mWhichChild;
84416c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        } else {
84553838d265e36fb50341af168f5a91c3341c3cfc3Adam Cohen            setDisplayedChild(mWhichChild, false);
84616c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        }
847b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    }
848b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
8493db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
8503db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Returns the View corresponding to the currently displayed child.
8513db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
8523db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @return The View currently displayed.
8533db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
8543db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #getDisplayedChild()
8553db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
8563db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public View getCurrentView() {
85744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        return getViewAtRelativeIndex(mActiveOffset);
8583db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
8593db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
8603db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
8613db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Returns the current animation used to animate a View that enters the screen.
8623db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
8633db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @return An Animation or null if none is set.
8643db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
8652794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @see #setInAnimation(android.animation.ObjectAnimator)
8663db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setInAnimation(android.content.Context, int)
8673db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
8682794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public ObjectAnimator getInAnimation() {
8693db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return mInAnimation;
8703db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
8713db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
8723db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
8733db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Specifies the animation used to animate a View that enters the screen.
8743db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
8753db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param inAnimation The animation started when a View enters the screen.
8763db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
8773db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #getInAnimation()
8783db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setInAnimation(android.content.Context, int)
8793db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
8802794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public void setInAnimation(ObjectAnimator inAnimation) {
8813db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mInAnimation = inAnimation;
8823db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
8833db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
8843db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
8853db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Returns the current animation used to animate a View that exits the screen.
8863db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
8873db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @return An Animation or null if none is set.
8883db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
8892794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @see #setOutAnimation(android.animation.ObjectAnimator)
8903db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setOutAnimation(android.content.Context, int)
8913db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
8922794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public ObjectAnimator getOutAnimation() {
8933db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return mOutAnimation;
8943db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
8953db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
8963db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
8973db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Specifies the animation used to animate a View that exit the screen.
8983db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
8993db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param outAnimation The animation started when a View exit the screen.
9003db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
9013db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #getOutAnimation()
9023db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setOutAnimation(android.content.Context, int)
9033db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
9042794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase    public void setOutAnimation(ObjectAnimator outAnimation) {
9053db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mOutAnimation = outAnimation;
9063db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
9073db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
9083db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
9093db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Specifies the animation used to animate a View that enters the screen.
9103db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
9113db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param context The application's environment.
9123db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param resourceID The resource id of the animation.
9133db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
9143db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #getInAnimation()
9152794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @see #setInAnimation(android.animation.ObjectAnimator)
9163db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
9173db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setInAnimation(Context context, int resourceID) {
9182794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        setInAnimation((ObjectAnimator) AnimatorInflater.loadAnimator(context, resourceID));
9193db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
9203db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
9213db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
9223db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Specifies the animation used to animate a View that exit the screen.
9233db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
9243db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param context The application's environment.
9253db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param resourceID The resource id of the animation.
9263db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
9273db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #getOutAnimation()
9282794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase     * @see #setOutAnimation(android.animation.ObjectAnimator)
9293db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
9303db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setOutAnimation(Context context, int resourceID) {
9312794eb3b02e2404d453d3ad22a8a85a138130a07Chet Haase        setOutAnimation((ObjectAnimator) AnimatorInflater.loadAnimator(context, resourceID));
9323db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
9333db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
9343db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
9353db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Indicates whether the current View should be animated the first time
9363db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * the ViewAnimation is displayed.
9373db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
9383db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param animate True to animate the current View the first time it is displayed,
9393db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *                false otherwise.
9403db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
9413db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setAnimateFirstView(boolean animate) {
9423db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mAnimateFirstTime = animate;
9433db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
9443db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
9453db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @Override
9463db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public int getBaseline() {
9473db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return (getCurrentView() != null) ? getCurrentView().getBaseline() : super.getBaseline();
9483db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
9493db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
9503db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @Override
9513db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public Adapter getAdapter() {
9523db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return mAdapter;
9533db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
9543db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
9553db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @Override
9563db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setAdapter(Adapter adapter) {
9578322834a2544a673a35c5d4ad0d5909b3ca37600Adam Cohen        if (mAdapter != null && mDataSetObserver != null) {
9588322834a2544a673a35c5d4ad0d5909b3ca37600Adam Cohen            mAdapter.unregisterDataSetObserver(mDataSetObserver);
9598322834a2544a673a35c5d4ad0d5909b3ca37600Adam Cohen        }
9608322834a2544a673a35c5d4ad0d5909b3ca37600Adam Cohen
9613db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mAdapter = adapter;
9621480fddea874a42adb43b4bcdac6704e4c3e110bAdam Cohen        checkFocus();
9633db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
9643db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (mAdapter != null) {
9653db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            mDataSetObserver = new AdapterDataSetObserver();
9663db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            mAdapter.registerDataSetObserver(mDataSetObserver);
967ef17dd497edc14ca753616862efaa3457e1df5daAdam Cohen            mItemCount = mAdapter.getCount();
9683db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
96944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        setFocusable(true);
97078db1aa9118edd71c2da28a2c23a0d875d1a707aAdam Cohen        mWhichChild = 0;
97178db1aa9118edd71c2da28a2c23a0d875d1a707aAdam Cohen        showOnly(mWhichChild, false);
9723db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
9733db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
9743db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
97544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Sets up this AdapterViewAnimator to use a remote views adapter which connects to a
97644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * RemoteViewsService through the specified intent.
97744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *
97844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param intent the intent used to identify the RemoteViewsService for the adapter to
97944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *        connect to.
9803db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
9813db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @android.view.RemotableViewMethod
9823db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setRemoteViewsAdapter(Intent intent) {
9839b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung        // Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
9849b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung        // service handling the specified intent.
9853ec9a45c36d3ca5ffbc6e85bbeb497b065e14155Winson Chung        if (mRemoteViewsAdapter != null) {
9863ec9a45c36d3ca5ffbc6e85bbeb497b065e14155Winson Chung            Intent.FilterComparison fcNew = new Intent.FilterComparison(intent);
9873ec9a45c36d3ca5ffbc6e85bbeb497b065e14155Winson Chung            Intent.FilterComparison fcOld = new Intent.FilterComparison(
9883ec9a45c36d3ca5ffbc6e85bbeb497b065e14155Winson Chung                    mRemoteViewsAdapter.getRemoteViewsServiceIntent());
9893ec9a45c36d3ca5ffbc6e85bbeb497b065e14155Winson Chung            if (fcNew.equals(fcOld)) {
9903ec9a45c36d3ca5ffbc6e85bbeb497b065e14155Winson Chung                return;
9913ec9a45c36d3ca5ffbc6e85bbeb497b065e14155Winson Chung            }
9929b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung        }
9932148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen        mDeferNotifyDataSetChanged = false;
9949b3a2cf2a0a482ce8212eb2775176dd4c23e8e9aWinson Chung        // Otherwise, create a new RemoteViewsAdapter for binding
9953db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mRemoteViewsAdapter = new RemoteViewsAdapter(getContext(), intent, this);
996335c3b681bf1c118d9bf22d1a508c87173632ec6Adam Cohen        if (mRemoteViewsAdapter.isDataReady()) {
997335c3b681bf1c118d9bf22d1a508c87173632ec6Adam Cohen            setAdapter(mRemoteViewsAdapter);
998335c3b681bf1c118d9bf22d1a508c87173632ec6Adam Cohen        }
9993db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
10003db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
1001a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen    /**
1002a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen     * Sets up the onClickHandler to be used by the RemoteViewsAdapter when inflating RemoteViews
1003a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen     *
1004a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen     * @param handler The OnClickHandler to use when inflating RemoteViews.
1005a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen     *
1006a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen     * @hide
1007a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen     */
1008a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen    public void setRemoteViewsOnClickHandler(OnClickHandler handler) {
1009a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen        // Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
1010a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen        // service handling the specified intent.
1011a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen        if (mRemoteViewsAdapter != null) {
1012a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen            mRemoteViewsAdapter.setRemoteViewsOnClickHandler(handler);
1013a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen        }
1014a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen    }
1015a6a4cbc18f7e5a3831d787d3f398e02c5eae6512Adam Cohen
10163db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @Override
10173db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setSelection(int position) {
10183db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        setDisplayedChild(position);
10193db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
10203db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
10213db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @Override
10223db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public View getSelectedView() {
102344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        return getViewAtRelativeIndex(mActiveOffset);
10243db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
10253db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
10263db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
10272148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen     * This defers a notifyDataSetChanged on the pending RemoteViewsAdapter if it has not
10282148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen     * connected yet.
10292148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen     */
10302148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen    public void deferNotifyDataSetChanged() {
10312148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen        mDeferNotifyDataSetChanged = true;
10322148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen    }
10332148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen
10342148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen    /**
10353db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Called back when the adapter connects to the RemoteViewsService.
10363db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
103716c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung    public boolean onRemoteAdapterConnected() {
10383db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (mRemoteViewsAdapter != mAdapter) {
10393db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            setAdapter(mRemoteViewsAdapter);
104016c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung
10412148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen            if (mDeferNotifyDataSetChanged) {
10422148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen                mRemoteViewsAdapter.notifyDataSetChanged();
10432148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen                mDeferNotifyDataSetChanged = false;
10442148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen            }
10452148d43eb23c702e834c93ae427f822f32d280a2Adam Cohen
104616c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            // Restore the previous position (see onRestoreInstanceState)
104716c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            if (mRestoreWhichChild > -1) {
104853838d265e36fb50341af168f5a91c3341c3cfc3Adam Cohen                setDisplayedChild(mRestoreWhichChild, false);
104916c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung                mRestoreWhichChild = -1;
105016c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            }
105116c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            return false;
1052fb60386b46d0c6216c765c10bd33ac42ca780917Adam Cohen        } else if (mRemoteViewsAdapter != null) {
1053fb60386b46d0c6216c765c10bd33ac42ca780917Adam Cohen            mRemoteViewsAdapter.superNotifyDataSetChanged();
105416c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung            return true;
10553db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
105616c8d8a558f94ec14ef52bb5ac11044e2d0d902cWinson Chung        return false;
10573db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
10583db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
10593db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
10603db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Called back when the adapter disconnects from the RemoteViewsService.
10613db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
10623db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void onRemoteAdapterDisconnected() {
1063fb60386b46d0c6216c765c10bd33ac42ca780917Adam Cohen        // If the remote adapter disconnects, we keep it around
1064fb60386b46d0c6216c765c10bd33ac42ca780917Adam Cohen        // since the currently displayed items are still cached.
1065fb60386b46d0c6216c765c10bd33ac42ca780917Adam Cohen        // Further, we want the service to eventually reconnect
1066fb60386b46d0c6216c765c10bd33ac42ca780917Adam Cohen        // when necessary, as triggered by this view requesting
1067fb60386b46d0c6216c765c10bd33ac42ca780917Adam Cohen        // items from the Adapter.
10683db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
1069a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen
10700e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen    /**
10710e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen     * Called by an {@link android.appwidget.AppWidgetHost} in order to advance the current view when
10720e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen     * it is being used within an app widget.
10730e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen     */
1074a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen    public void advance() {
1075a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen        showNext();
1076a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen    }
1077a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen
10780e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen    /**
10790e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen     * Called by an {@link android.appwidget.AppWidgetHost} to indicate that it will be
10800e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen     * automatically advancing the views of this {@link AdapterViewAnimator} by calling
10810e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen     * {@link AdapterViewAnimator#advance()} at some point in the future. This allows subclasses to
10820e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen     * perform any required setup, for example, to stop automatically advancing their children.
10830e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen     */
10840e2de6d7187ef67ec00a2f2544450caa4a239c39Adam Cohen    public void fyiWillBeAdvancedByHostKThx() {
1085a02fdf1ba03fad71cc80a89dfc74b17456d5b4a5Adam Cohen    }
10868a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
10878a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
10888a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
10898a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityEvent(event);
10908a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        event.setClassName(AdapterViewAnimator.class.getName());
10918a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
10928a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov
10938a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    @Override
10948a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
10958a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        super.onInitializeAccessibilityNodeInfo(info);
10968a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov        info.setClassName(AdapterViewAnimator.class.getName());
10978a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov    }
10983db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen}
1099