Fields Summary |
---|
private static final String | TAG |
int | mWhichChildThe 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 | mRestoreWhichChildThe index of the child to restore after the asynchronous connection from the
RemoteViewsAdapter has been. |
boolean | mAnimateFirstTimeWhether or not the first view(s) should be animated in |
int | mActiveOffsetRepresents where the in the current window of
views the current mDisplayedChild sits |
int | mMaxNumActiveViewsThe 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 | mViewsMapMap of the children of the {@link AdapterViewAnimator}. |
ArrayList | mPreviousViewsList of views pending removal from the {@link AdapterViewAnimator} |
int | mCurrentWindowStartThe index, relative to the adapter, of the beginning of the window of views |
int | mCurrentWindowEndThe index, relative to the adapter, of the end of the window of views |
int | mCurrentWindowStartUnboundedThe same as {@link #mCurrentWindowStart}, except when the we have bounded
{@link #mCurrentWindowStart} to be non-negative |
AdapterDataSetObserver | mDataSetObserverListens for data changes from the adapter |
Adapter | mAdapterThe {@link Adapter} for this {@link AdapterViewAnimator} |
RemoteViewsAdapter | mRemoteViewsAdapterThe {@link RemoteViewsAdapter} for this {@link AdapterViewAnimator} |
boolean | mDeferNotifyDataSetChangedThe remote adapter containing the data to be displayed by this view to be set |
boolean | mFirstTimeSpecifies whether this is the first time the animator is showing views |
boolean | mLoopViewsSpecifies if the animator should wrap from 0 to the end and vice versa
or have hard boundaries at the beginning and end |
int | mReferenceChildWidthThe 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 | mInAnimationIn and out animations. |
android.animation.ObjectAnimator | mOutAnimation |
private int | mTouchModeCurrent touch state. |
static final int | TOUCH_MODE_NONEPrivate 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 |
Methods Summary |
---|
private void | addChild(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 void | advance()Called by an {@link android.appwidget.AppWidgetHost} in order to advance the current view when
it is being used within an app widget.
showNext();
|
void | applyTransformForChildAtIndex(android.view.View child, int relativeIndex)To be overridden by subclasses. This method applies a view / index specific
transform to the child view.
|
void | cancelHandleClick()
View v = getCurrentView();
if (v != null) {
hideTapFeedback(v);
}
mTouchMode = TOUCH_MODE_NONE;
|
void | checkForAndHandleDataChanged()
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;
|
void | configureViewAnimator(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
if (activeOffset > numVisibleViews - 1) {
// Throw an exception here.
}
mMaxNumActiveViews = numVisibleViews;
mActiveOffset = activeOffset;
mPreviousViews.clear();
mViewsMap.clear();
removeAllViewsInLayout();
mCurrentWindowStart = 0;
mCurrentWindowEnd = -1;
|
LayoutParams | createOrReuseLayoutParams(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 void | deferNotifyDataSetChanged()This defers a notifyDataSetChanged on the pending RemoteViewsAdapter if it has not
connected yet.
mDeferNotifyDataSetChanged = true;
|
public void | fyiWillBeAdvancedByHostKThx()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 Adapter | getAdapter()
return mAdapter;
|
public int | getBaseline()
return (getCurrentView() != null) ? getCurrentView().getBaseline() : super.getBaseline();
|
public android.view.View | getCurrentView()Returns the View corresponding to the currently displayed child.
return getViewAtRelativeIndex(mActiveOffset);
|
android.animation.ObjectAnimator | getDefaultInAnimation()
ObjectAnimator anim = ObjectAnimator.ofFloat(null, "alpha", 0.0f, 1.0f);
anim.setDuration(DEFAULT_ANIMATION_DURATION);
return anim;
|
android.animation.ObjectAnimator | getDefaultOutAnimation()
ObjectAnimator anim = ObjectAnimator.ofFloat(null, "alpha", 1.0f, 0.0f);
anim.setDuration(DEFAULT_ANIMATION_DURATION);
return anim;
|
public int | getDisplayedChild()Returns the index of the currently displayed child view.
return mWhichChild;
|
FrameLayout | getFrameForChild()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 new FrameLayout(mContext);
|
public android.animation.ObjectAnimator | getInAnimation()Returns the current animation used to animate a View that enters the screen.
return mInAnimation;
|
private android.widget.AdapterViewAnimator$ViewAndMetaData | getMetaDataForChild(android.view.View child)
for (ViewAndMetaData vm: mViewsMap.values()) {
if (vm.view == child) {
return vm;
}
}
return null;
|
int | getNumActiveViews()
if (mAdapter != null) {
return Math.min(getCount() + 1, mMaxNumActiveViews);
} else {
return mMaxNumActiveViews;
}
|
public android.animation.ObjectAnimator | getOutAnimation()Returns the current animation used to animate a View that exits the screen.
return mOutAnimation;
|
public android.view.View | getSelectedView()
return getViewAtRelativeIndex(mActiveOffset);
|
android.view.View | getViewAtRelativeIndex(int relativeIndex)Get the view at this index relative to the current window's start
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;
|
int | getWindowSize()
if (mAdapter != null) {
int adapterCount = getCount();
if (adapterCount <= getNumActiveViews() && mLoopViews) {
return adapterCount*mMaxNumActiveViews;
} else {
return adapterCount;
}
} else {
return 0;
}
|
void | hideTapFeedback(android.view.View v)
v.setPressed(false);
|
private void | initViewAnimator()Initialize this {@link AdapterViewAnimator}
mPreviousViews = new ArrayList<Integer>();
|
private void | measureChildren()
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));
}
|
int | modulo(int pos, int size)
if (size > 0) {
return (size + (pos % size)) % size;
} else {
return 0;
}
|
public void | onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)
super.onInitializeAccessibilityEvent(event);
event.setClassName(AdapterViewAnimator.class.getName());
|
public void | onInitializeAccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo info)
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(AdapterViewAnimator.class.getName());
|
protected void | onLayout(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 void | onMeasure(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 boolean | onRemoteAdapterConnected()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 void | onRemoteAdapterDisconnected()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 void | onRestoreInstanceState(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.Parcelable | onSaveInstanceState()
Parcelable superState = super.onSaveInstanceState();
if (mRemoteViewsAdapter != null) {
mRemoteViewsAdapter.saveRemoteViewsCache();
}
return new SavedState(superState, mWhichChild);
|
public boolean | onTouchEvent(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;
|
void | refreshChildren()
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 void | setAdapter(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 void | setAnimateFirstView(boolean animate)Indicates whether the current View should be animated the first time
the ViewAnimation is displayed.
mAnimateFirstTime = animate;
|
public void | setDisplayedChild(int whichChild)Sets which child view will be displayed.
setDisplayedChild(whichChild, true);
|
private void | setDisplayedChild(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 void | setInAnimation(android.animation.ObjectAnimator inAnimation)Specifies the animation used to animate a View that enters the screen.
mInAnimation = inAnimation;
|
public void | setInAnimation(android.content.Context context, int resourceID)Specifies the animation used to animate a View that enters the screen.
setInAnimation((ObjectAnimator) AnimatorInflater.loadAnimator(context, resourceID));
|
public void | setOutAnimation(android.animation.ObjectAnimator outAnimation)Specifies the animation used to animate a View that exit the screen.
mOutAnimation = outAnimation;
|
public void | setOutAnimation(android.content.Context context, int resourceID)Specifies the animation used to animate a View that exit the screen.
setOutAnimation((ObjectAnimator) AnimatorInflater.loadAnimator(context, resourceID));
|
public void | setRemoteViewsAdapter(android.content.Intent intent)Sets up this AdapterViewAnimator to use a remote views adapter which connects to a
RemoteViewsService through the specified intent.
// 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 void | setRemoteViewsOnClickHandler(android.widget.RemoteViews.OnClickHandler handler)Sets up the onClickHandler to be used by the RemoteViewsAdapter when inflating RemoteViews
// 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 void | setSelection(int position)
setDisplayedChild(position);
|
public void | showNext()Manually shows the next child.
setDisplayedChild(mWhichChild + 1);
|
void | showOnly(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}.
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 void | showPrevious()Manually shows the previous child.
setDisplayedChild(mWhichChild - 1);
|
void | showTapFeedback(android.view.View v)
v.setPressed(true);
|
void | transformViewForTransition(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
if (fromIndex == -1) {
mInAnimation.setTarget(view);
mInAnimation.start();
} else if (toIndex == -1) {
mOutAnimation.setTarget(view);
mOutAnimation.start();
}
|