FileDocCategorySizeDatePackage
AdapterViewAnimator.javaAPI DocAndroid 5.1 API39668Thu Mar 12 22:22:10 GMT 2015android.widget

AdapterViewAnimator

public abstract class AdapterViewAnimator extends AdapterView implements Advanceable, RemoteViewsAdapter.RemoteAdapterConnectionCallback
Base class for a {@link AdapterView} that will perform animations when switching between its views.
attr
ref android.R.styleable#AdapterViewAnimator_inAnimation
attr
ref android.R.styleable#AdapterViewAnimator_outAnimation
attr
ref android.R.styleable#AdapterViewAnimator_animateFirstView
attr
ref android.R.styleable#AdapterViewAnimator_loopViews

Fields Summary
private static final String
TAG
int
mWhichChild
The index of the current child, which appears anywhere from the beginning to the end of the current set of children, as specified by {@link #mActiveOffset}
private int
mRestoreWhichChild
The index of the child to restore after the asynchronous connection from the RemoteViewsAdapter has been.
boolean
mAnimateFirstTime
Whether or not the first view(s) should be animated in
int
mActiveOffset
Represents where the in the current window of views the current mDisplayedChild sits
int
mMaxNumActiveViews
The number of views that the {@link AdapterViewAnimator} keeps as children at any given time (not counting views that are pending removal, see {@link #mPreviousViews}).
HashMap
mViewsMap
Map of the children of the {@link AdapterViewAnimator}.
ArrayList
mPreviousViews
List of views pending removal from the {@link AdapterViewAnimator}
int
mCurrentWindowStart
The index, relative to the adapter, of the beginning of the window of views
int
mCurrentWindowEnd
The index, relative to the adapter, of the end of the window of views
int
mCurrentWindowStartUnbounded
The same as {@link #mCurrentWindowStart}, except when the we have bounded {@link #mCurrentWindowStart} to be non-negative
AdapterDataSetObserver
mDataSetObserver
Listens for data changes from the adapter
Adapter
mAdapter
The {@link Adapter} for this {@link AdapterViewAnimator}
RemoteViewsAdapter
mRemoteViewsAdapter
The {@link RemoteViewsAdapter} for this {@link AdapterViewAnimator}
boolean
mDeferNotifyDataSetChanged
The remote adapter containing the data to be displayed by this view to be set
boolean
mFirstTime
Specifies whether this is the first time the animator is showing views
boolean
mLoopViews
Specifies if the animator should wrap from 0 to the end and vice versa or have hard boundaries at the beginning and end
int
mReferenceChildWidth
The width and height of some child, used as a size reference in-case our dimensions are unspecified by the parent.
int
mReferenceChildHeight
android.animation.ObjectAnimator
mInAnimation
In and out animations.
android.animation.ObjectAnimator
mOutAnimation
private int
mTouchMode
Current touch state.
static final int
TOUCH_MODE_NONE
Private touch states.
static final int
TOUCH_MODE_DOWN_IN_CURRENT_VIEW
static final int
TOUCH_MODE_HANDLED
private Runnable
mPendingCheckForTap
private static final int
DEFAULT_ANIMATION_DURATION
Constructors Summary
public AdapterViewAnimator(android.content.Context context)


       
        this(context, null);
    
public AdapterViewAnimator(android.content.Context context, android.util.AttributeSet attrs)

        this(context, attrs, 0);
    
public AdapterViewAnimator(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr)

        this(context, attrs, defStyleAttr, 0);
    
public AdapterViewAnimator(android.content.Context context, android.util.AttributeSet attrs, int defStyleAttr, int defStyleRes)

        super(context, attrs, defStyleAttr, defStyleRes);

        final TypedArray a = context.obtainStyledAttributes(attrs,
                com.android.internal.R.styleable.AdapterViewAnimator, defStyleAttr, defStyleRes);
        int resource = a.getResourceId(
                com.android.internal.R.styleable.AdapterViewAnimator_inAnimation, 0);
        if (resource > 0) {
            setInAnimation(context, resource);
        } else {
            setInAnimation(getDefaultInAnimation());
        }

        resource = a.getResourceId(com.android.internal.R.styleable.AdapterViewAnimator_outAnimation, 0);
        if (resource > 0) {
            setOutAnimation(context, resource);
        } else {
            setOutAnimation(getDefaultOutAnimation());
        }

        boolean flag = a.getBoolean(
                com.android.internal.R.styleable.AdapterViewAnimator_animateFirstView, true);
        setAnimateFirstView(flag);

        mLoopViews = a.getBoolean(
                com.android.internal.R.styleable.AdapterViewAnimator_loopViews, false);

        a.recycle();

        initViewAnimator();
    
Methods Summary
private voidaddChild(android.view.View child)

        addViewInLayout(child, -1, createOrReuseLayoutParams(child));

        // This code is used to obtain a reference width and height of a child in case we need
        // to decide our own size. TODO: Do we want to update the size of the child that we're
        // using for reference size? If so, when?
        if (mReferenceChildWidth == -1 || mReferenceChildHeight == -1) {
            int measureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
            child.measure(measureSpec, measureSpec);
            mReferenceChildWidth = child.getMeasuredWidth();
            mReferenceChildHeight = child.getMeasuredHeight();
        }
    
public voidadvance()
Called by an {@link android.appwidget.AppWidgetHost} in order to advance the current view when it is being used within an app widget.

        showNext();
    
voidapplyTransformForChildAtIndex(android.view.View child, int relativeIndex)
To be overridden by subclasses. This method applies a view / index specific transform to the child view.

param
child
param
relativeIndex

    
voidcancelHandleClick()

        View v = getCurrentView();
        if (v != null) {
            hideTapFeedback(v);
        }
        mTouchMode = TOUCH_MODE_NONE;
    
voidcheckForAndHandleDataChanged()

        boolean dataChanged = mDataChanged;
        if (dataChanged) {
            post(new Runnable() {
                public void run() {
                    handleDataChanged();
                    // if the data changes, mWhichChild might be out of the bounds of the adapter
                    // in this case, we reset mWhichChild to the beginning
                    if (mWhichChild >= getWindowSize()) {
                        mWhichChild = 0;

                        showOnly(mWhichChild, false);
                    } else if (mOldItemCount != getCount()) {
                        showOnly(mWhichChild, false);
                    }
                    refreshChildren();
                    requestLayout();
                }
            });
        }
        mDataChanged = false;
    
voidconfigureViewAnimator(int numVisibleViews, int activeOffset)
This method is used by subclasses to configure the animator to display the desired number of views, and specify the offset

param
numVisibleViews The number of views the animator keeps in the {@link ViewGroup}
param
activeOffset This parameter specifies where the current index ({@link #mWhichChild}) sits within the window. For example if activeOffset is 1, and numVisibleViews is 3, and {@link #setDisplayedChild(int)} is called with 10, then the effective window will be the indexes 9, 10, and 11. In the same example, if activeOffset were 0, then the window would instead contain indexes 10, 11 and 12.
param
shouldLoop If the animator is show view 0, and setPrevious() is called, do we we loop back to the end, or do we do nothing

        if (activeOffset > numVisibleViews - 1) {
            // Throw an exception here.
        }
        mMaxNumActiveViews = numVisibleViews;
        mActiveOffset = activeOffset;
        mPreviousViews.clear();
        mViewsMap.clear();
        removeAllViewsInLayout();
        mCurrentWindowStart = 0;
        mCurrentWindowEnd = -1;
    
LayoutParamscreateOrReuseLayoutParams(android.view.View v)

        final ViewGroup.LayoutParams currentLp = v.getLayoutParams();
        if (currentLp instanceof ViewGroup.LayoutParams) {
            LayoutParams lp = (LayoutParams) currentLp;
            return lp;
        }
        return new ViewGroup.LayoutParams(0, 0);
    
public voiddeferNotifyDataSetChanged()
This defers a notifyDataSetChanged on the pending RemoteViewsAdapter if it has not connected yet.

        mDeferNotifyDataSetChanged = true;
    
public voidfyiWillBeAdvancedByHostKThx()
Called by an {@link android.appwidget.AppWidgetHost} to indicate that it will be automatically advancing the views of this {@link AdapterViewAnimator} by calling {@link AdapterViewAnimator#advance()} at some point in the future. This allows subclasses to perform any required setup, for example, to stop automatically advancing their children.

    
public AdaptergetAdapter()

        return mAdapter;
    
public intgetBaseline()

        return (getCurrentView() != null) ? getCurrentView().getBaseline() : super.getBaseline();
    
public android.view.ViewgetCurrentView()
Returns the View corresponding to the currently displayed child.

return
The View currently displayed.
see
#getDisplayedChild()

        return getViewAtRelativeIndex(mActiveOffset);
    
android.animation.ObjectAnimatorgetDefaultInAnimation()

        ObjectAnimator anim = ObjectAnimator.ofFloat(null, "alpha", 0.0f, 1.0f);
        anim.setDuration(DEFAULT_ANIMATION_DURATION);
        return anim;
    
android.animation.ObjectAnimatorgetDefaultOutAnimation()

        ObjectAnimator anim = ObjectAnimator.ofFloat(null, "alpha", 1.0f, 0.0f);
        anim.setDuration(DEFAULT_ANIMATION_DURATION);
        return anim;
    
public intgetDisplayedChild()
Returns the index of the currently displayed child view.

        return mWhichChild;
    
FrameLayoutgetFrameForChild()
This method can be overridden so that subclasses can provide a custom frame in which their children can live. For example, StackView adds padding to its childrens' frames so as to accomodate for the highlight effect.

return
The FrameLayout into which children can be placed.

        return new FrameLayout(mContext);
    
public android.animation.ObjectAnimatorgetInAnimation()
Returns the current animation used to animate a View that enters the screen.

return
An Animation or null if none is set.
see
#setInAnimation(android.animation.ObjectAnimator)
see
#setInAnimation(android.content.Context, int)

        return mInAnimation;
    
private android.widget.AdapterViewAnimator$ViewAndMetaDatagetMetaDataForChild(android.view.View child)

        for (ViewAndMetaData vm: mViewsMap.values()) {
            if (vm.view == child) {
                return vm;
            }
        }
        return null;
     
intgetNumActiveViews()

        if (mAdapter != null) {
            return Math.min(getCount() + 1, mMaxNumActiveViews);
        } else {
            return mMaxNumActiveViews;
        }
    
public android.animation.ObjectAnimatorgetOutAnimation()
Returns the current animation used to animate a View that exits the screen.

return
An Animation or null if none is set.
see
#setOutAnimation(android.animation.ObjectAnimator)
see
#setOutAnimation(android.content.Context, int)

        return mOutAnimation;
    
public android.view.ViewgetSelectedView()

        return getViewAtRelativeIndex(mActiveOffset);
    
android.view.ViewgetViewAtRelativeIndex(int relativeIndex)
Get the view at this index relative to the current window's start

param
relativeIndex Position relative to the current window's start
return
View at this index, null if the index is outside the bounds

        if (relativeIndex >= 0 && relativeIndex <= getNumActiveViews() - 1 && mAdapter != null) {
            int i = modulo(mCurrentWindowStartUnbounded + relativeIndex, getWindowSize());
            if (mViewsMap.get(i) != null) {
                return mViewsMap.get(i).view;
            }
        }
        return null;
    
intgetWindowSize()

        if (mAdapter != null) {
            int adapterCount = getCount();
            if (adapterCount <= getNumActiveViews() && mLoopViews) {
                return adapterCount*mMaxNumActiveViews;
            } else {
                return adapterCount;
            }
        } else {
            return 0;
        }
    
voidhideTapFeedback(android.view.View v)

        v.setPressed(false);
    
private voidinitViewAnimator()
Initialize this {@link AdapterViewAnimator}

        mPreviousViews = new ArrayList<Integer>();
    
private voidmeasureChildren()

        final int count = getChildCount();
        final int childWidth = getMeasuredWidth() - mPaddingLeft - mPaddingRight;
        final int childHeight = getMeasuredHeight() - mPaddingTop - mPaddingBottom;

        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY));
        }
    
intmodulo(int pos, int size)

        if (size > 0) {
            return (size + (pos % size)) % size;
        } else {
            return 0;
        }
    
public voidonInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)

        super.onInitializeAccessibilityEvent(event);
        event.setClassName(AdapterViewAnimator.class.getName());
    
public voidonInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo info)

        super.onInitializeAccessibilityNodeInfo(info);
        info.setClassName(AdapterViewAnimator.class.getName());
    
protected voidonLayout(boolean changed, int left, int top, int right, int bottom)

        checkForAndHandleDataChanged();

        final int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            final View child = getChildAt(i);

            int childRight = mPaddingLeft + child.getMeasuredWidth();
            int childBottom = mPaddingTop + child.getMeasuredHeight();

            child.layout(mPaddingLeft, mPaddingTop, childRight, childBottom);
        }
    
protected voidonMeasure(int widthMeasureSpec, int heightMeasureSpec)

        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        final int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
        final int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

        boolean haveChildRefSize = (mReferenceChildWidth != -1 && mReferenceChildHeight != -1);

        // We need to deal with the case where our parent hasn't told us how
        // big we should be. In this case we try to use the desired size of the first
        // child added.
        if (heightSpecMode == MeasureSpec.UNSPECIFIED) {
            heightSpecSize = haveChildRefSize ? mReferenceChildHeight + mPaddingTop +
                    mPaddingBottom : 0;
        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
            if (haveChildRefSize) {
                int height = mReferenceChildHeight + mPaddingTop + mPaddingBottom;
                if (height > heightSpecSize) {
                    heightSpecSize |= MEASURED_STATE_TOO_SMALL;
                } else {
                    heightSpecSize = height;
                }
            }
        }

        if (widthSpecMode == MeasureSpec.UNSPECIFIED) {
            widthSpecSize = haveChildRefSize ? mReferenceChildWidth + mPaddingLeft +
                    mPaddingRight : 0;
        } else if (heightSpecMode == MeasureSpec.AT_MOST) {
            if (haveChildRefSize) {
                int width = mReferenceChildWidth + mPaddingLeft + mPaddingRight;
                if (width > widthSpecSize) {
                    widthSpecSize |= MEASURED_STATE_TOO_SMALL;
                } else {
                    widthSpecSize = width;
                }
            }
        }

        setMeasuredDimension(widthSpecSize, heightSpecSize);
        measureChildren();
    
public booleanonRemoteAdapterConnected()
Called back when the adapter connects to the RemoteViewsService.

        if (mRemoteViewsAdapter != mAdapter) {
            setAdapter(mRemoteViewsAdapter);

            if (mDeferNotifyDataSetChanged) {
                mRemoteViewsAdapter.notifyDataSetChanged();
                mDeferNotifyDataSetChanged = false;
            }

            // Restore the previous position (see onRestoreInstanceState)
            if (mRestoreWhichChild > -1) {
                setDisplayedChild(mRestoreWhichChild, false);
                mRestoreWhichChild = -1;
            }
            return false;
        } else if (mRemoteViewsAdapter != null) {
            mRemoteViewsAdapter.superNotifyDataSetChanged();
            return true;
        }
        return false;
    
public voidonRemoteAdapterDisconnected()
Called back when the adapter disconnects from the RemoteViewsService.

        // If the remote adapter disconnects, we keep it around
        // since the currently displayed items are still cached.
        // Further, we want the service to eventually reconnect
        // when necessary, as triggered by this view requesting
        // items from the Adapter.
    
public voidonRestoreInstanceState(android.os.Parcelable state)

        SavedState ss = (SavedState) state;
        super.onRestoreInstanceState(ss.getSuperState());

        // Here we set mWhichChild in addition to setDisplayedChild
        // We do the former in case mAdapter is null, and hence setDisplayedChild won't
        // set mWhichChild
        mWhichChild = ss.whichChild;

        // When using RemoteAdapters, the async connection process can lead to
        // onRestoreInstanceState to be called before setAdapter(), so we need to save the previous
        // values to restore the list position after we connect, and can skip setting the displayed
        // child until then.
        if (mRemoteViewsAdapter != null && mAdapter == null) {
            mRestoreWhichChild = mWhichChild;
        } else {
            setDisplayedChild(mWhichChild, false);
        }
    
public android.os.ParcelableonSaveInstanceState()

    

    
       
        Parcelable superState = super.onSaveInstanceState();
        if (mRemoteViewsAdapter != null) {
            mRemoteViewsAdapter.saveRemoteViewsCache();
        }
        return new SavedState(superState, mWhichChild);
    
public booleanonTouchEvent(android.view.MotionEvent ev)

        int action = ev.getAction();
        boolean handled = false;
        switch (action) {
            case MotionEvent.ACTION_DOWN: {
                View v = getCurrentView();
                if (v != null) {
                    if (isTransformedTouchPointInView(ev.getX(), ev.getY(), v, null)) {
                        if (mPendingCheckForTap == null) {
                            mPendingCheckForTap = new CheckForTap();
                        }
                        mTouchMode = TOUCH_MODE_DOWN_IN_CURRENT_VIEW;
                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
                    }
                }
                break;
            }
            case MotionEvent.ACTION_MOVE: break;
            case MotionEvent.ACTION_POINTER_UP: break;
            case MotionEvent.ACTION_UP: {
                if (mTouchMode == TOUCH_MODE_DOWN_IN_CURRENT_VIEW) {
                    final View v = getCurrentView();
                    final ViewAndMetaData viewData = getMetaDataForChild(v);
                    if (v != null) {
                        if (isTransformedTouchPointInView(ev.getX(), ev.getY(), v, null)) {
                            final Handler handler = getHandler();
                            if (handler != null) {
                                handler.removeCallbacks(mPendingCheckForTap);
                            }
                            showTapFeedback(v);
                            postDelayed(new Runnable() {
                                public void run() {
                                    hideTapFeedback(v);
                                    post(new Runnable() {
                                        public void run() {
                                            if (viewData != null) {
                                                performItemClick(v, viewData.adapterPosition,
                                                        viewData.itemId);
                                            } else {
                                                performItemClick(v, 0, 0);
                                            }
                                        }
                                    });
                                }
                            }, ViewConfiguration.getPressedStateDuration());
                            handled = true;
                        }
                    }
                }
                mTouchMode = TOUCH_MODE_NONE;
                break;
            }
            case MotionEvent.ACTION_CANCEL: {
                View v = getCurrentView();
                if (v != null) {
                    hideTapFeedback(v);
                }
                mTouchMode = TOUCH_MODE_NONE;
            }
        }
        return handled;
    
voidrefreshChildren()

        if (mAdapter == null) return;
        for (int i = mCurrentWindowStart; i <= mCurrentWindowEnd; i++) {
            int index = modulo(i, getWindowSize());

            int adapterCount = getCount();
            // get the fresh child from the adapter
            final View updatedChild = mAdapter.getView(modulo(i, adapterCount), null, this);

            if (updatedChild.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
                updatedChild.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
            }

            if (mViewsMap.containsKey(index)) {
                final FrameLayout fl = (FrameLayout) mViewsMap.get(index).view;
                // add the new child to the frame, if it exists
                if (updatedChild != null) {
                    // flush out the old child
                    fl.removeAllViewsInLayout();
                    fl.addView(updatedChild);
                }
            }
        }
    
public voidsetAdapter(Adapter adapter)

        if (mAdapter != null && mDataSetObserver != null) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        }

        mAdapter = adapter;
        checkFocus();

        if (mAdapter != null) {
            mDataSetObserver = new AdapterDataSetObserver();
            mAdapter.registerDataSetObserver(mDataSetObserver);
            mItemCount = mAdapter.getCount();
        }
        setFocusable(true);
        mWhichChild = 0;
        showOnly(mWhichChild, false);
    
public voidsetAnimateFirstView(boolean animate)
Indicates whether the current View should be animated the first time the ViewAnimation is displayed.

param
animate True to animate the current View the first time it is displayed, false otherwise.

        mAnimateFirstTime = animate;
    
public voidsetDisplayedChild(int whichChild)
Sets which child view will be displayed.

param
whichChild the index of the child view to display

        setDisplayedChild(whichChild, true);
    
private voidsetDisplayedChild(int whichChild, boolean animate)

        if (mAdapter != null) {
            mWhichChild = whichChild;
            if (whichChild >= getWindowSize()) {
                mWhichChild = mLoopViews ? 0 : getWindowSize() - 1;
            } else if (whichChild < 0) {
                mWhichChild = mLoopViews ? getWindowSize() - 1 : 0;
            }

            boolean hasFocus = getFocusedChild() != null;
            // This will clear old focus if we had it
            showOnly(mWhichChild, animate);
            if (hasFocus) {
                // Try to retake focus if we had it
                requestFocus(FOCUS_FORWARD);
            }
        }
    
public voidsetInAnimation(android.animation.ObjectAnimator inAnimation)
Specifies the animation used to animate a View that enters the screen.

param
inAnimation The animation started when a View enters the screen.
see
#getInAnimation()
see
#setInAnimation(android.content.Context, int)

        mInAnimation = inAnimation;
    
public voidsetInAnimation(android.content.Context context, int resourceID)
Specifies the animation used to animate a View that enters the screen.

param
context The application's environment.
param
resourceID The resource id of the animation.
see
#getInAnimation()
see
#setInAnimation(android.animation.ObjectAnimator)

        setInAnimation((ObjectAnimator) AnimatorInflater.loadAnimator(context, resourceID));
    
public voidsetOutAnimation(android.animation.ObjectAnimator outAnimation)
Specifies the animation used to animate a View that exit the screen.

param
outAnimation The animation started when a View exit the screen.
see
#getOutAnimation()
see
#setOutAnimation(android.content.Context, int)

        mOutAnimation = outAnimation;
    
public voidsetOutAnimation(android.content.Context context, int resourceID)
Specifies the animation used to animate a View that exit the screen.

param
context The application's environment.
param
resourceID The resource id of the animation.
see
#getOutAnimation()
see
#setOutAnimation(android.animation.ObjectAnimator)

        setOutAnimation((ObjectAnimator) AnimatorInflater.loadAnimator(context, resourceID));
    
public voidsetRemoteViewsAdapter(android.content.Intent intent)
Sets up this AdapterViewAnimator to use a remote views adapter which connects to a RemoteViewsService through the specified intent.

param
intent the intent used to identify the RemoteViewsService for the adapter to connect to.

        // Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
        // service handling the specified intent.
        if (mRemoteViewsAdapter != null) {
            Intent.FilterComparison fcNew = new Intent.FilterComparison(intent);
            Intent.FilterComparison fcOld = new Intent.FilterComparison(
                    mRemoteViewsAdapter.getRemoteViewsServiceIntent());
            if (fcNew.equals(fcOld)) {
                return;
            }
        }
        mDeferNotifyDataSetChanged = false;
        // Otherwise, create a new RemoteViewsAdapter for binding
        mRemoteViewsAdapter = new RemoteViewsAdapter(getContext(), intent, this);
        if (mRemoteViewsAdapter.isDataReady()) {
            setAdapter(mRemoteViewsAdapter);
        }
    
public voidsetRemoteViewsOnClickHandler(android.widget.RemoteViews.OnClickHandler handler)
Sets up the onClickHandler to be used by the RemoteViewsAdapter when inflating RemoteViews

param
handler The OnClickHandler to use when inflating RemoteViews.
hide

        // Ensure that we don't already have a RemoteViewsAdapter that is bound to an existing
        // service handling the specified intent.
        if (mRemoteViewsAdapter != null) {
            mRemoteViewsAdapter.setRemoteViewsOnClickHandler(handler);
        }
    
public voidsetSelection(int position)

        setDisplayedChild(position);
    
public voidshowNext()
Manually shows the next child.

        setDisplayedChild(mWhichChild + 1);
    
voidshowOnly(int childIndex, boolean animate)
Shows only the specified child. The other displays Views exit the screen, optionally with the with the {@link #getOutAnimation() out animation} and the specified child enters the screen, optionally with the {@link #getInAnimation() in animation}.

param
childIndex The index of the child to be shown.
param
animate Whether or not to use the in and out animations, defaults to true.

        if (mAdapter == null) return;
        final int adapterCount = getCount();
        if (adapterCount == 0) return;

        for (int i = 0; i < mPreviousViews.size(); i++) {
            View viewToRemove = mViewsMap.get(mPreviousViews.get(i)).view;
            mViewsMap.remove(mPreviousViews.get(i));
            viewToRemove.clearAnimation();
            if (viewToRemove instanceof ViewGroup) {
                ViewGroup vg = (ViewGroup) viewToRemove;
                vg.removeAllViewsInLayout();
            }
            // applyTransformForChildAtIndex here just allows for any cleanup
            // associated with this view that may need to be done by a subclass
            applyTransformForChildAtIndex(viewToRemove, -1);

            removeViewInLayout(viewToRemove);
        }
        mPreviousViews.clear();
        int newWindowStartUnbounded = childIndex - mActiveOffset;
        int newWindowEndUnbounded = newWindowStartUnbounded + getNumActiveViews() - 1;
        int newWindowStart = Math.max(0, newWindowStartUnbounded);
        int newWindowEnd = Math.min(adapterCount - 1, newWindowEndUnbounded);

        if (mLoopViews) {
            newWindowStart = newWindowStartUnbounded;
            newWindowEnd = newWindowEndUnbounded;
        }
        int rangeStart = modulo(newWindowStart, getWindowSize());
        int rangeEnd = modulo(newWindowEnd, getWindowSize());

        boolean wrap = false;
        if (rangeStart > rangeEnd) {
            wrap = true;
        }

        // This section clears out any items that are in our active views list
        // but are outside the effective bounds of our window (this is becomes an issue
        // at the extremities of the list, eg. where newWindowStartUnbounded < 0 or
        // newWindowEndUnbounded > adapterCount - 1
        for (Integer index : mViewsMap.keySet()) {
            boolean remove = false;
            if (!wrap && (index < rangeStart || index > rangeEnd)) {
                remove = true;
            } else if (wrap && (index > rangeEnd && index < rangeStart)) {
                remove = true;
            }

            if (remove) {
                View previousView = mViewsMap.get(index).view;
                int oldRelativeIndex = mViewsMap.get(index).relativeIndex;

                mPreviousViews.add(index);
                transformViewForTransition(oldRelativeIndex, -1, previousView, animate);
            }
        }

        // If the window has changed
        if (!(newWindowStart == mCurrentWindowStart && newWindowEnd == mCurrentWindowEnd &&
              newWindowStartUnbounded == mCurrentWindowStartUnbounded)) {
            // Run through the indices in the new range
            for (int i = newWindowStart; i <= newWindowEnd; i++) {

                int index = modulo(i, getWindowSize());
                int oldRelativeIndex;
                if (mViewsMap.containsKey(index)) {
                    oldRelativeIndex = mViewsMap.get(index).relativeIndex;
                } else {
                    oldRelativeIndex = -1;
                }
                int newRelativeIndex = i - newWindowStartUnbounded;

                // If this item is in the current window, great, we just need to apply
                // the transform for it's new relative position in the window, and animate
                // between it's current and new relative positions
                boolean inOldRange = mViewsMap.containsKey(index) && !mPreviousViews.contains(index);

                if (inOldRange) {
                    View view = mViewsMap.get(index).view;
                    mViewsMap.get(index).relativeIndex = newRelativeIndex;
                    applyTransformForChildAtIndex(view, newRelativeIndex);
                    transformViewForTransition(oldRelativeIndex, newRelativeIndex, view, animate);

                // Otherwise this view is new to the window
                } else {
                    // Get the new view from the adapter, add it and apply any transform / animation
                    final int adapterPosition = modulo(i, adapterCount);
                    View newView = mAdapter.getView(adapterPosition, null, this);
                    long itemId = mAdapter.getItemId(adapterPosition);

                    // We wrap the new view in a FrameLayout so as to respect the contract
                    // with the adapter, that is, that we don't modify this view directly
                    FrameLayout fl = getFrameForChild();

                    // If the view from the adapter is null, we still keep an empty frame in place
                    if (newView != null) {
                       fl.addView(newView);
                    }
                    mViewsMap.put(index, new ViewAndMetaData(fl, newRelativeIndex,
                            adapterPosition, itemId));
                    addChild(fl);
                    applyTransformForChildAtIndex(fl, newRelativeIndex);
                    transformViewForTransition(-1, newRelativeIndex, fl, animate);
                }
                mViewsMap.get(index).view.bringToFront();
            }
            mCurrentWindowStart = newWindowStart;
            mCurrentWindowEnd = newWindowEnd;
            mCurrentWindowStartUnbounded = newWindowStartUnbounded;
            if (mRemoteViewsAdapter != null) {
                int adapterStart = modulo(mCurrentWindowStart, adapterCount);
                int adapterEnd = modulo(mCurrentWindowEnd, adapterCount);
                mRemoteViewsAdapter.setVisibleRangeHint(adapterStart, adapterEnd);
            }
        }
        requestLayout();
        invalidate();
    
public voidshowPrevious()
Manually shows the previous child.

        setDisplayedChild(mWhichChild - 1);
    
voidshowTapFeedback(android.view.View v)

        v.setPressed(true);
    
voidtransformViewForTransition(int fromIndex, int toIndex, android.view.View view, boolean animate)
This class should be overridden by subclasses to customize view transitions within the set of visible views

param
fromIndex The relative index within the window that the view was in, -1 if it wasn't in the window
param
toIndex The relative index within the window that the view is going to, -1 if it is being removed
param
view The view that is being animated

        if (fromIndex == -1) {
            mInAnimation.setTarget(view);
            mInAnimation.start();
        } else if (toIndex == -1) {
            mOutAnimation.setTarget(view);
            mOutAnimation.start();
        }