AdapterViewAnimator.java revision bd0136a2fde1d81a835f94efe3193569b10d99ff
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
1944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohenimport java.util.ArrayList;
2044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
21a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haaseimport android.animation.ObjectAnimator;
223db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.content.Context;
233db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.content.Intent;
243db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.content.res.TypedArray;
253db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.os.Handler;
263db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.os.Looper;
27b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohenimport android.os.Parcel;
28b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohenimport android.os.Parcelable;
293db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.util.AttributeSet;
303db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.view.View;
3144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohenimport android.view.ViewGroup;
32839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohenimport android.view.ViewGroup.LayoutParams;
333db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.view.animation.Animation;
343db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohenimport android.view.animation.AnimationUtils;
353db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
363db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen/**
373db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * Base class for a {@link AdapterView} that will perform animations
383db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * when switching between its views.
393db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen *
403db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * @attr ref android.R.styleable#AdapterViewAnimator_inAnimation
413db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * @attr ref android.R.styleable#AdapterViewAnimator_outAnimation
423db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen * @attr ref android.R.styleable#AdapterViewAnimator_animateFirstView
433db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen */
4444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohenpublic abstract class AdapterViewAnimator extends AdapterView<Adapter>
4544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        implements RemoteViewsAdapter.RemoteAdapterConnectionCallback{
463db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    private static final String TAG = "RemoteViewAnimator";
473db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
4844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
4944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The index of the current child, which appears anywhere from the beginning
5044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * to the end of the current set of children, as specified by {@link #mActiveOffset}
5144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
523db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    int mWhichChild = 0;
5344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
5444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
5544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Whether or not the first view(s) should be animated in
5644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
573db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    boolean mAnimateFirstTime = true;
583db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
5944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
6044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *  Represents where the in the current window of
6144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *  views the current <code>mDisplayedChild</code> sits
6244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
6344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    int mActiveOffset = 0;
6444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
6544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
6644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The number of views that the {@link AdapterViewAnimator} keeps as children at any
6744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * given time (not counting views that are pending removal, see {@link #mPreviousViews}).
6844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
6944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    int mNumActiveViews = 1;
7044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
7144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
7244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Array of the children of the {@link AdapterViewAnimator}. This array
7344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * is accessed in a circular fashion
7444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
7544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    View[] mActiveViews;
7644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
7744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
7844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * List of views pending removal from the {@link AdapterViewAnimator}
7944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
8044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    ArrayList<View> mPreviousViews;
8144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
8244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
8344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The index, relative to the adapter, of the beginning of the window of views
8444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
8544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    int mCurrentWindowStart = 0;
8644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
8744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
8844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The index, relative to the adapter, of the end of the window of views
8944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
9044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    int mCurrentWindowEnd = -1;
9144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
9244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
9344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The same as {@link #mCurrentWindowStart}, except when the we have bounded
9444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * {@link #mCurrentWindowStart} to be non-negative
9544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
9644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    int mCurrentWindowStartUnbounded = 0;
9744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
9844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
9944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Handler to post events to the main thread
10044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
10144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    Handler mMainQueue;
10244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
10344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
10444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Listens for data changes from the adapter
10544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
1063db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    AdapterDataSetObserver mDataSetObserver;
1073db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
10844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
10944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The {@link Adapter} for this {@link AdapterViewAnimator}
11044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
11144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    Adapter mAdapter;
11244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
11344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
11444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * The {@link RemoteViewsAdapter} for this {@link AdapterViewAnimator}
11544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
11644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    RemoteViewsAdapter mRemoteViewsAdapter;
11744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
11844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
11944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Specifies whether this is the first time the animator is showing views
12044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
12144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    boolean mFirstTime = true;
1223db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
12344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
124b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen     * Specifies if the animator should wrap from 0 to the end and vice versa
125b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen     * or have hard boundaries at the beginning and end
126b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen     */
127b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    boolean mShouldLoop = true;
128b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
129b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    /**
130839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen     * The width and height of some child, used as a size reference in-case our
131839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen     * dimensions are unspecified by the parent.
132839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen     */
133839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    int mReferenceChildWidth = -1;
134839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    int mReferenceChildHeight = -1;
135839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
136839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    /**
13744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * TODO: Animation stuff is still in flux, waiting on the new framework to settle a bit.
13844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
1393db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    Animation mInAnimation;
1403db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    Animation mOutAnimation;
14144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    private  ArrayList<View> mViewsToBringToFront;
1423db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
1433db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public AdapterViewAnimator(Context context) {
1443db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        super(context);
1455b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy        initViewAnimator();
1463db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
1473db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
1483db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public AdapterViewAnimator(Context context, AttributeSet attrs) {
1493db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        super(context, attrs);
1503db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
15144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        TypedArray a = context.obtainStyledAttributes(attrs,
15244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                com.android.internal.R.styleable.ViewAnimator);
15344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        int resource = a.getResourceId(
15444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                com.android.internal.R.styleable.ViewAnimator_inAnimation, 0);
1553db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (resource > 0) {
1563db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            setInAnimation(context, resource);
1573db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
1583db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
1593db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        resource = a.getResourceId(com.android.internal.R.styleable.ViewAnimator_outAnimation, 0);
1603db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (resource > 0) {
1613db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            setOutAnimation(context, resource);
1623db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
1633db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
16444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        boolean flag = a.getBoolean(
16544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                com.android.internal.R.styleable.ViewAnimator_animateFirstView, true);
1663db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        setAnimateFirstView(flag);
1673db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
1683db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        a.recycle();
1693db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
1705b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy        initViewAnimator();
1713db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
1723db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
1733db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
1743db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Initialize this {@link AdapterViewAnimator}
1753db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
1765b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy    private void initViewAnimator() {
1773db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mMainQueue = new Handler(Looper.myLooper());
17844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mActiveViews = new View[mNumActiveViews];
17944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mPreviousViews = new ArrayList<View>();
18044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mViewsToBringToFront = new ArrayList<View>();
18144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    }
18244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
18344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
18444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * This method is used by subclasses to configure the animator to display the
18544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * desired number of views, and specify the offset
18644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *
18744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param numVisibleViews The number of views the animator keeps in the {@link ViewGroup}
1885b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy     * @param activeOffset This parameter specifies where the current index ({@link #mWhichChild})
18944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *        sits within the window. For example if activeOffset is 1, and numVisibleViews is 3,
1905b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy     *        and {@link #setDisplayedChild(int)} is called with 10, then the effective window will
1915b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy     *        be the indexes 9, 10, and 11. In the same example, if activeOffset were 0, then the
19244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *        window would instead contain indexes 10, 11 and 12.
193b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen     * @param shouldLoop If the animator is show view 0, and setPrevious() is called, do we
194b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen     *        we loop back to the end, or do we do nothing
19544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
196b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen     void configureViewAnimator(int numVisibleViews, int activeOffset, boolean shouldLoop) {
19744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        if (activeOffset > numVisibleViews - 1) {
19844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            // Throw an exception here.
19944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
20044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mNumActiveViews = numVisibleViews;
20144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mActiveOffset = activeOffset;
20244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mActiveViews = new View[mNumActiveViews];
20344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mPreviousViews.clear();
20444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        removeAllViewsInLayout();
20544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mCurrentWindowStart = 0;
20644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mCurrentWindowEnd = -1;
207b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        mShouldLoop = shouldLoop;
20844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    }
20944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
21044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
21144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * This class should be overridden by subclasses to customize view transitions within
21244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * the set of visible views
21344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *
21444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param fromIndex The relative index within the window that the view was in, -1 if it wasn't
21544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *        in the window
21644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param toIndex The relative index within the window that the view is going to, -1 if it is
21744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *        being removed
21844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param view The view that is being animated
21944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
22044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    void animateViewForTransition(int fromIndex, int toIndex, View view) {
221a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase        ObjectAnimator pa;
22244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        if (fromIndex == -1) {
223b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            view.setAlpha(0.0f);
224a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase            pa = new ObjectAnimator(400, view, "alpha", 0.0f, 1.0f);
22544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            pa.start();
22644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        } else if (toIndex == -1) {
227a18a86b43e40e3c15dcca0ae0148d641be9b25feChet Haase            pa = new ObjectAnimator(400, view, "alpha", 1.0f, 0.0f);
22844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            pa.start();
22944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
2303db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
2313db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
2323db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
2333db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Sets which child view will be displayed.
2343db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
2353db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param whichChild the index of the child view to display
2363db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
2373db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setDisplayedChild(int whichChild) {
2383db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (mAdapter != null) {
2393db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            mWhichChild = whichChild;
2403db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            if (whichChild >= mAdapter.getCount()) {
241b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen                mWhichChild = mShouldLoop ? 0 : mAdapter.getCount() - 1;
2423db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            } else if (whichChild < 0) {
243b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen                mWhichChild = mShouldLoop ? mAdapter.getCount() - 1 : 0;
2443db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            }
2453db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
2463db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            boolean hasFocus = getFocusedChild() != null;
2473db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            // This will clear old focus if we had it
2483db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            showOnly(mWhichChild);
2493db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            if (hasFocus) {
2503db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen                // Try to retake focus if we had it
2513db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen                requestFocus(FOCUS_FORWARD);
2523db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            }
2533db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
2543db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
2553db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
2563db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
2573db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Return default inAnimation. To be overriden by subclasses.
2583db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
25944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    Animation getDefaultInAnimation() {
2603db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return null;
2613db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
2623db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
2633db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
26444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Return default outAnimation. To be overridden by subclasses.
2653db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
26644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    Animation getDefaultOutAnimation() {
2673db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return null;
2683db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
2693db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
2703db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
27144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * To be overridden by subclasses. This method applies a view / index specific
27244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * transform to the child view.
27344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *
27444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param child
27544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param relativeIndex
27644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
27744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    void applyTransformForChildAtIndex(View child, int relativeIndex) {
27844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    }
27944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
28044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
2813db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Returns the index of the currently displayed child view.
2823db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
2833db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public int getDisplayedChild() {
2843db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return mWhichChild;
2853db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
2863db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
2873db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
2883db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Manually shows the next child.
2893db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
2903db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void showNext() {
2913db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        setDisplayedChild(mWhichChild + 1);
2923db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
2933db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
2943db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
2953db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Manually shows the previous child.
2963db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
2973db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void showPrevious() {
2983db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        setDisplayedChild(mWhichChild - 1);
2993db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
3003db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
3013db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
3023db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Shows only the specified child. The other displays Views exit the screen,
3033db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * optionally with the with the {@link #getOutAnimation() out animation} and
3043db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * the specified child enters the screen, optionally with the
3053db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * {@link #getInAnimation() in animation}.
3063db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
3073db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param childIndex The index of the child to be shown.
3083db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param animate Whether or not to use the in and out animations, defaults
3093db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *            to true.
3103db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
3113db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    void showOnly(int childIndex, boolean animate) {
3123db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        showOnly(childIndex, animate, false);
3133db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
3143db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
31544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    private int modulo(int pos, int size) {
31644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        return (size + (pos % size)) % size;
3173db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
3183db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
31944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    /**
32044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Get the view at this index relative to the current window's start
32144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *
32244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param relativeIndex Position relative to the current window's start
32344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @return View at this index, null if the index is outside the bounds
32444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     */
32544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    View getViewAtRelativeIndex(int relativeIndex) {
32644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        if (relativeIndex >= 0 && relativeIndex <= mNumActiveViews - 1) {
32744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            int index = mCurrentWindowStartUnbounded + relativeIndex;
32844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            return mActiveViews[modulo(index, mNumActiveViews)];
32944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
33044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        return null;
33144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    }
3323db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
3339b073948cfb84c0dd04f8a94ee1f7f263f027c83Adam Cohen    LayoutParams createOrReuseLayoutParams(View v) {
3345b53f9186e7812c93bc578d18e92cb123481fcbcRomain Guy        final ViewGroup.LayoutParams currentLp = v.getLayoutParams();
3359b073948cfb84c0dd04f8a94ee1f7f263f027c83Adam Cohen        if (currentLp instanceof ViewGroup.LayoutParams) {
336b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            LayoutParams lp = (LayoutParams) currentLp;
337b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            return lp;
33844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
3399b073948cfb84c0dd04f8a94ee1f7f263f027c83Adam Cohen        return new ViewGroup.LayoutParams(0, 0);
34044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    }
3413db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
342bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen    private void refreshChildren() {
343bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen        for (int i = mCurrentWindowStart; i <= mCurrentWindowEnd; i++) {
344bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen            int index = modulo(i, mNumActiveViews);
345bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen
346bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen            // get the fresh child from the adapter
347bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen            View updatedChild = mAdapter.getView(i, null, this);
348bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen
349bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen            if (mActiveViews[index] != null) {
350bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                FrameLayout fl = (FrameLayout) mActiveViews[index];
351bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                // flush out the old child
352bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                fl.removeAllViewsInLayout();
353bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                // add the new child to the frame, if it exists
354bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                if (updatedChild != null) {
355bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    fl.addView(updatedChild);
356bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                }
357bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen            }
358bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen        }
359bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen    }
360bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen
36144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen    void showOnly(int childIndex, boolean animate, boolean onLayout) {
36244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        if (mAdapter == null) return;
3633db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
36444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        for (int i = 0; i < mPreviousViews.size(); i++) {
36544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            View viewToRemove = mPreviousViews.get(i);
36644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            viewToRemove.clearAnimation();
3673d07af03421f4727ef7e97c5c19e6ade50b19060Adam Cohen            if (viewToRemove instanceof ViewGroup) {
3683d07af03421f4727ef7e97c5c19e6ade50b19060Adam Cohen                ViewGroup vg = (ViewGroup) viewToRemove;
3693d07af03421f4727ef7e97c5c19e6ade50b19060Adam Cohen                vg.removeAllViewsInLayout();
3703d07af03421f4727ef7e97c5c19e6ade50b19060Adam Cohen            }
37144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            // applyTransformForChildAtIndex here just allows for any cleanup
37244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            // associated with this view that may need to be done by a subclass
37344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            applyTransformForChildAtIndex(viewToRemove, -1);
3743d07af03421f4727ef7e97c5c19e6ade50b19060Adam Cohen
37544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            removeViewInLayout(viewToRemove);
37644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
37744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mPreviousViews.clear();
37844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        int newWindowStartUnbounded = childIndex - mActiveOffset;
37944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        int newWindowEndUnbounded = newWindowStartUnbounded + mNumActiveViews - 1;
38044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        int newWindowStart = Math.max(0, newWindowStartUnbounded);
38144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        int newWindowEnd = Math.min(mAdapter.getCount(), newWindowEndUnbounded);
38244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
38344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        // This section clears out any items that are in our mActiveViews list
38444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        // but are outside the effective bounds of our window (this is becomes an issue
38544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        // at the extremities of the list, eg. where newWindowStartUnbounded < 0 or
38644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        // newWindowEndUnbounded > mAdapter.getCount() - 1
38744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        for (int i = newWindowStartUnbounded; i < newWindowEndUnbounded; i++) {
38844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            if (i < newWindowStart || i > newWindowEnd) {
38944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                int index = modulo(i, mNumActiveViews);
39044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                if (mActiveViews[index] != null) {
39144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    View previousView = mActiveViews[index];
39244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    mPreviousViews.add(previousView);
39344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    int previousViewRelativeIndex = modulo(index - mCurrentWindowStart,
39444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                            mNumActiveViews);
39544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    animateViewForTransition(previousViewRelativeIndex, -1, previousView);
396b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen                    mActiveViews[index] = null;
39744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                }
3983db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            }
39944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
4003db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
40144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        // If the window has changed
40244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        if (! (newWindowStart == mCurrentWindowStart && newWindowEnd == mCurrentWindowEnd)) {
40344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            // Run through the indices in the new range
40444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            for (int i = newWindowStart; i <= newWindowEnd; i++) {
40544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
40644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                int oldRelativeIndex = i - mCurrentWindowStartUnbounded;
40744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                int newRelativeIndex = i - newWindowStartUnbounded;
40844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                int index = modulo(i, mNumActiveViews);
40944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
41044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                // If this item is in the current window, great, we just need to apply
41144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                // the transform for it's new relative position in the window, and animate
41244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                // between it's current and new relative positions
41344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                if (i >= mCurrentWindowStart && i <= mCurrentWindowEnd) {
41444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    View view = mActiveViews[index];
41544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    applyTransformForChildAtIndex(view, newRelativeIndex);
41644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    animateViewForTransition(oldRelativeIndex, newRelativeIndex, view);
41744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
41844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                // Otherwise this view is new, so first we have to displace the view that's
41944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                // taking the new view's place within our cache (a circular array)
42044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                } else {
42144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    if (mActiveViews[index] != null) {
42244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                        View previousView = mActiveViews[index];
42344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                        mPreviousViews.add(previousView);
42444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                        int previousViewRelativeIndex = modulo(index - mCurrentWindowStart,
42544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                                mNumActiveViews);
42644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                        animateViewForTransition(previousViewRelativeIndex, -1, previousView);
42744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
42844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                        if (mCurrentWindowStart > newWindowStart) {
42944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                            mViewsToBringToFront.add(previousView);
43044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                        }
43144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    }
4323db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
43344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    // We've cleared a spot for the new view. Get it from the adapter, add it
43444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    // and apply any transform / animation
43544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    View newView = mAdapter.getView(i, null, this);
436bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen
437bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    // We wrap the new view in a FrameLayout so as to respect the contract
438bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    // with the adapter, that is, that we don't modify this view directly
439bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    FrameLayout fl = new FrameLayout(mContext);
440bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen
441bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    // If the view from the adapter is null, we still keep an empty frame in place
44244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    if (newView != null) {
443bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                       fl.addView(newView);
44444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    }
445bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    mActiveViews[index] = fl;
446bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    addChild(fl);
447bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    applyTransformForChildAtIndex(fl, newRelativeIndex);
448bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                    animateViewForTransition(-1, newRelativeIndex, fl);
4493db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen                }
45044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                mActiveViews[index].bringToFront();
4513db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            }
4523db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
45344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            for (int i = 0; i < mViewsToBringToFront.size(); i++) {
45444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                View v = mViewsToBringToFront.get(i);
45544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                v.bringToFront();
4563db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            }
45744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            mViewsToBringToFront.clear();
4583db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
45944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            mCurrentWindowStart = newWindowStart;
46044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            mCurrentWindowEnd = newWindowEnd;
46144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            mCurrentWindowStartUnbounded = newWindowStartUnbounded;
46244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        }
46344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen
46444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        mFirstTime = false;
46544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        if (!onLayout) {
46644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            requestLayout();
46744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            invalidate();
46844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        } else {
46944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            // If the Adapter tries to layout the current view when we get it using getView
47044729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            // above the layout will end up being ignored since we are currently laying out, so
47144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            // we post a delayed requestLayout and invalidate
47244729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            mMainQueue.post(new Runnable() {
47344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                @Override
47444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                public void run() {
47544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    requestLayout();
47644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                    invalidate();
47744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen                }
47844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen            });
4793db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
4803db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
4813db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
482839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    private void addChild(View child) {
483839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        addViewInLayout(child, -1, createOrReuseLayoutParams(child));
484839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
485839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // This code is used to obtain a reference width and height of a child in case we need
486839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // to decide our own size. TODO: Do we want to update the size of the child that we're
487839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // using for reference size? If so, when?
488839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        if (mReferenceChildWidth == -1 || mReferenceChildHeight == -1) {
489839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            int measureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
490839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            child.measure(measureSpec, measureSpec);
491839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            mReferenceChildWidth = child.getMeasuredWidth();
492839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            mReferenceChildHeight = child.getMeasuredHeight();
493839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        }
494839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    }
495839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
496839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    private void measureChildren() {
497839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        final int count = getChildCount();
498839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        final int childWidth = mMeasuredWidth - mPaddingLeft - mPaddingRight;
499839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        final int childHeight = mMeasuredHeight - mPaddingTop - mPaddingBottom;
500839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
501839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        for (int i = 0; i < count; i++) {
502839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            final View child = getChildAt(i);
503839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
504839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen                    MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
505839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        }
506839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    }
507839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
508839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    @Override
509839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
510839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
511839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
512839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
513839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
514839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
515839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        boolean haveChildRefSize = (mReferenceChildWidth != -1 && mReferenceChildHeight != -1);
516839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
517839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // We need to deal with the case where our parent hasn't told us how
518839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // big we should be. In this case we try to use the desired size of the first
519839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        // child added.
520839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        if (heightSpecMode == MeasureSpec.UNSPECIFIED) {
521839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            heightSpecSize = haveChildRefSize ? mReferenceChildHeight + mPaddingTop +
522839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen                    mPaddingBottom : 0;
523839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
524839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            heightSpecSize = haveChildRefSize ? Math.min(mReferenceChildHeight + mPaddingTop +
525839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen                    mPaddingBottom, heightSpecSize) : 0;
526839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        }
527839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
528839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        if (widthSpecMode == MeasureSpec.UNSPECIFIED) {
529839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            widthSpecSize = haveChildRefSize ? mReferenceChildWidth + mPaddingLeft +
530839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen                    mPaddingRight : 0;
531839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
532839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            widthSpecSize = haveChildRefSize ? Math.min(mReferenceChildWidth + mPaddingLeft +
533839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen                    mPaddingRight, widthSpecSize) : 0;
534839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        }
535839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
536839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        setMeasuredDimension(widthSpecSize, heightSpecSize);
537839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen        measureChildren();
538839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen    }
539839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen
5403db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @Override
5413db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
5423db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        boolean dataChanged = mDataChanged;
5433db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (dataChanged) {
5443db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            handleDataChanged();
5453db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
5463db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            // if the data changes, mWhichChild might be out of the bounds of the adapter
5473db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            // in this case, we reset mWhichChild to the beginning
548bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen            if (mWhichChild >= mAdapter.getCount()) {
5493db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen                mWhichChild = 0;
5503db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
551bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen                showOnly(mWhichChild, true, true);
552bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen            }
553bd0136a2fde1d81a835f94efe3193569b10d99ffAdam Cohen            refreshChildren();
5543db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
5553db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
5563db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        final int childCount = getChildCount();
5573db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        for (int i = 0; i < childCount; i++) {
5583db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            final View child = getChildAt(i);
5593db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
5603db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            int childRight = mPaddingLeft + child.getMeasuredWidth();
5613db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            int childBottom = mPaddingTop + child.getMeasuredHeight();
5623db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
563839f4a54e5a6fe602dbc5998b01412d809eba722Adam Cohen            child.layout(mPaddingLeft, mPaddingTop, childRight, childBottom);
5643db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
5653db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mDataChanged = false;
5663db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
5673db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
568b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    static class SavedState extends BaseSavedState {
569b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        int whichChild;
570b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
571b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        /**
572b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen         * Constructor called from {@link AdapterViewAnimator#onSaveInstanceState()}
573b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen         */
574b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        SavedState(Parcelable superState, int whichChild) {
575b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            super(superState);
576b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            this.whichChild = whichChild;
577b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        }
578b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
579b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        /**
580b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen         * Constructor called from {@link #CREATOR}
581b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen         */
582b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        private SavedState(Parcel in) {
583b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            super(in);
584b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            whichChild = in.readInt();
585b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        }
586b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
587b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        @Override
588b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        public void writeToParcel(Parcel out, int flags) {
589b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            super.writeToParcel(out, flags);
590b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            out.writeInt(whichChild);
591b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        }
592b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
593b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        @Override
594b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        public String toString() {
595b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            return "AdapterViewAnimator.SavedState{ whichChild = " + whichChild + " }";
596b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        }
597b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
598b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        public static final Parcelable.Creator<SavedState> CREATOR
599b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen                = new Parcelable.Creator<SavedState>() {
600b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            public SavedState createFromParcel(Parcel in) {
601b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen                return new SavedState(in);
602b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            }
603b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
604b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            public SavedState[] newArray(int size) {
605b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen                return new SavedState[size];
606b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen            }
607b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        };
608b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    }
609b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
610b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    @Override
611b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    public Parcelable onSaveInstanceState() {
612b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        Parcelable superState = super.onSaveInstanceState();
613b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        return new SavedState(superState, mWhichChild);
614b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    }
615b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
616b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    @Override
617b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    public void onRestoreInstanceState(Parcelable state) {
618b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        SavedState ss = (SavedState) state;
619b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        super.onRestoreInstanceState(ss.getSuperState());
620b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
621b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        // Here we set mWhichChild in addition to setDisplayedChild
622b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        // We do the former in case mAdapter is null, and hence setDisplayedChild won't
623b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        // set mWhichChild
624b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        mWhichChild = ss.whichChild;
625b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen        setDisplayedChild(mWhichChild);
626b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen    }
627b04f7ad90b7d5d5e0998e3b56960004cf56e6e8fAdam Cohen
6283db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
6293db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Shows only the specified child. The other displays Views exit the screen
6303db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * with the {@link #getOutAnimation() out animation} and the specified child
6313db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * enters the screen with the {@link #getInAnimation() in animation}.
6323db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
6333db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param childIndex The index of the child to be shown.
6343db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
6353db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    void showOnly(int childIndex) {
6363db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        final boolean animate = (!mFirstTime || mAnimateFirstTime);
6373db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        showOnly(childIndex, animate);
6383db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
6393db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
6403db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
6413db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Returns the View corresponding to the currently displayed child.
6423db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
6433db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @return The View currently displayed.
6443db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
6453db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #getDisplayedChild()
6463db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
6473db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public View getCurrentView() {
64844729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        return getViewAtRelativeIndex(mActiveOffset);
6493db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
6503db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
6513db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
6523db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Returns the current animation used to animate a View that enters the screen.
6533db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
6543db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @return An Animation or null if none is set.
6553db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
6563db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setInAnimation(android.view.animation.Animation)
6573db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setInAnimation(android.content.Context, int)
6583db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
6593db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public Animation getInAnimation() {
6603db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return mInAnimation;
6613db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
6623db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
6633db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
6643db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Specifies the animation used to animate a View that enters the screen.
6653db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
6663db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param inAnimation The animation started when a View enters the screen.
6673db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
6683db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #getInAnimation()
6693db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setInAnimation(android.content.Context, int)
6703db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
6713db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setInAnimation(Animation inAnimation) {
6723db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mInAnimation = inAnimation;
6733db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
6743db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
6753db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
6763db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Returns the current animation used to animate a View that exits the screen.
6773db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
6783db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @return An Animation or null if none is set.
6793db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
6803db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setOutAnimation(android.view.animation.Animation)
6813db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setOutAnimation(android.content.Context, int)
6823db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
6833db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public Animation getOutAnimation() {
6843db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return mOutAnimation;
6853db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
6863db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
6873db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
6883db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Specifies the animation used to animate a View that exit the screen.
6893db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
6903db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param outAnimation The animation started when a View exit the screen.
6913db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
6923db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #getOutAnimation()
6933db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setOutAnimation(android.content.Context, int)
6943db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
6953db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setOutAnimation(Animation outAnimation) {
6963db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mOutAnimation = outAnimation;
6973db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
6983db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
6993db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
7003db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Specifies the animation used to animate a View that enters the screen.
7013db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
7023db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param context The application's environment.
7033db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param resourceID The resource id of the animation.
7043db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
7053db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #getInAnimation()
7063db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setInAnimation(android.view.animation.Animation)
7073db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
7083db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setInAnimation(Context context, int resourceID) {
7093db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        setInAnimation(AnimationUtils.loadAnimation(context, resourceID));
7103db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
7113db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7123db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
7133db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Specifies the animation used to animate a View that exit the screen.
7143db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
7153db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param context The application's environment.
7163db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param resourceID The resource id of the animation.
7173db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
7183db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #getOutAnimation()
7193db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @see #setOutAnimation(android.view.animation.Animation)
7203db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
7213db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setOutAnimation(Context context, int resourceID) {
7223db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        setOutAnimation(AnimationUtils.loadAnimation(context, resourceID));
7233db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
7243db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7253db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
7263db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Indicates whether the current View should be animated the first time
7273db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * the ViewAnimation is displayed.
7283db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *
7293db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * @param animate True to animate the current View the first time it is displayed,
7303db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     *                false otherwise.
7313db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
7323db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setAnimateFirstView(boolean animate) {
7333db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mAnimateFirstTime = animate;
7343db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
7353db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7363db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @Override
7373db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public int getBaseline() {
7383db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return (getCurrentView() != null) ? getCurrentView().getBaseline() : super.getBaseline();
7393db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
7403db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7413db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @Override
7423db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public Adapter getAdapter() {
7433db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        return mAdapter;
7443db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
7453db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7463db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @Override
7473db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setAdapter(Adapter adapter) {
7488322834a2544a673a35c5d4ad0d5909b3ca37600Adam Cohen        if (mAdapter != null && mDataSetObserver != null) {
7498322834a2544a673a35c5d4ad0d5909b3ca37600Adam Cohen            mAdapter.unregisterDataSetObserver(mDataSetObserver);
7508322834a2544a673a35c5d4ad0d5909b3ca37600Adam Cohen        }
7518322834a2544a673a35c5d4ad0d5909b3ca37600Adam Cohen
7523db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mAdapter = adapter;
7531480fddea874a42adb43b4bcdac6704e4c3e110bAdam Cohen        checkFocus();
7543db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7553db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (mAdapter != null) {
7563db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            mDataSetObserver = new AdapterDataSetObserver();
7573db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            mAdapter.registerDataSetObserver(mDataSetObserver);
7583db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
75944729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        setFocusable(true);
7603db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
7613db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7623db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
76344729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * Sets up this AdapterViewAnimator to use a remote views adapter which connects to a
76444729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * RemoteViewsService through the specified intent.
76544729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *
76644729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     * @param intent the intent used to identify the RemoteViewsService for the adapter to
76744729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen     *        connect to.
7683db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
7693db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @android.view.RemotableViewMethod
7703db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setRemoteViewsAdapter(Intent intent) {
7713db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        mRemoteViewsAdapter = new RemoteViewsAdapter(getContext(), intent, this);
7723db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
7733db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7743db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @Override
7753db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void setSelection(int position) {
7763db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        setDisplayedChild(position);
7773db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
7783db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7793db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    @Override
7803db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public View getSelectedView() {
78144729e3d1c01265858eec566c7b7c676c46a7916Adam Cohen        return getViewAtRelativeIndex(mActiveOffset);
7823db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
7833db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7843db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
7853db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Called back when the adapter connects to the RemoteViewsService.
7863db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
7873db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void onRemoteAdapterConnected() {
7883db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (mRemoteViewsAdapter != mAdapter) {
7893db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            setAdapter(mRemoteViewsAdapter);
7903db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
7913db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
7923db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen
7933db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    /**
7943db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     * Called back when the adapter disconnects from the RemoteViewsService.
7953db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen     */
7963db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    public void onRemoteAdapterDisconnected() {
7973db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        if (mRemoteViewsAdapter != mAdapter) {
7983db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            mRemoteViewsAdapter = null;
7993db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen            setAdapter(mRemoteViewsAdapter);
8003db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen        }
8013db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen    }
8023db40678d33c2b5f90c380966d36b3e10ed11f05Adam Cohen}
803