Merge "Cleaning up StackView" into honeycomb
diff --git a/api/11.xml b/api/11.xml
index d17325f..de121e2 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -29889,6 +29889,17 @@
  visibility="public"
 >
 </method>
+<method name="isRemoving"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isResumed"
  return="boolean"
  abstract="false"
@@ -260418,7 +260429,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/api/current.xml b/api/current.xml
index 0122b83..ad9fe5d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -260440,7 +260440,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index e34a204..b505c85 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -246,7 +246,7 @@
      *        being removed
      * @param view The view that is being animated
      */
-    void animateViewForTransition(int fromIndex, int toIndex, View view) {
+    void transformViewForTransition(int fromIndex, int toIndex, View view, boolean animate) {
         if (fromIndex == -1) {
             mInAnimation.setTarget(view);
             mInAnimation.start();
@@ -473,7 +473,7 @@
                 int oldRelativeIndex = mViewsMap.get(index).index;
 
                 mPreviousViews.add(index);
-                animateViewForTransition(oldRelativeIndex, -1, previousView);
+                transformViewForTransition(oldRelativeIndex, -1, previousView, animate);
             }
         }
 
@@ -501,7 +501,7 @@
                     View view = mViewsMap.get(index).view;
                     mViewsMap.get(index).index = newRelativeIndex;
                     applyTransformForChildAtIndex(view, newRelativeIndex);
-                    animateViewForTransition(oldRelativeIndex, newRelativeIndex, view);
+                    transformViewForTransition(oldRelativeIndex, newRelativeIndex, view, animate);
 
                 // Otherwise this view is new to the window
                 } else {
@@ -519,7 +519,7 @@
                     mViewsMap.put(index, new ViewAndIndex(fl, newRelativeIndex));
                     addChild(fl);
                     applyTransformForChildAtIndex(fl, newRelativeIndex);
-                    animateViewForTransition(-1, newRelativeIndex, fl);
+                    transformViewForTransition(-1, newRelativeIndex, fl, animate);
                 }
                 mViewsMap.get(index).view.bringToFront();
             }
@@ -695,9 +695,9 @@
                     if (mWhichChild >= getWindowSize()) {
                         mWhichChild = 0;
 
-                        showOnly(mWhichChild, true);
+                        showOnly(mWhichChild, false);
                     } else if (mOldItemCount != getCount()) {
-                        showOnly(mWhichChild, true);
+                        showOnly(mWhichChild, false);
                     }
                     refreshChildren();
                     requestLayout();
@@ -916,7 +916,8 @@
             mItemCount = mAdapter.getCount();
         }
         setFocusable(true);
-        setDisplayedChild(0);
+        mWhichChild = 0;
+        showOnly(mWhichChild, false);
     }
 
     /**
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 03c073c..d57d5c6 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -69,7 +69,7 @@
     private float mNewPerspectiveShiftY;
 
     @SuppressWarnings({"FieldCanBeLocal"})
-    private static final float PERSPECTIVE_SCALE_FACTOR = 0.f;
+    private static final float PERSPECTIVE_SCALE_FACTOR = 0f;
 
     /**
      * Represent the two possible stack modes, one where items slide up, and the other
@@ -193,19 +193,16 @@
     /**
      * Animate the views between different relative indexes within the {@link AdapterViewAnimator}
      */
-    void animateViewForTransition(int fromIndex, int toIndex, final View view) {
+    void transformViewForTransition(int fromIndex, int toIndex, final View view, boolean animate) {
         ObjectAnimator alphaOa = null;
         ObjectAnimator oldAlphaOa = null;
 
-        // If there is currently an alpha animation on this view, we need
-        // to know about it, and may need to cancel it so as not to interfere with
-        // a new alpha animation.
-        Object tag = view.getTag(com.android.internal.R.id.viewAlphaAnimation);
-        if (tag instanceof WeakReference<?>) {
-            Object obj = ((WeakReference<?>) tag).get();
-            if (obj instanceof ObjectAnimator) {
-                oldAlphaOa = (ObjectAnimator) obj;
-            }
+        if (!animate) {
+            ((StackFrame) view).cancelSliderAnimator();
+            view.setRotationX(0f);
+            LayoutParams lp = (LayoutParams) view.getLayoutParams();
+            lp.setVerticalOffset(0);
+            lp.setHorizontalOffset(0);
         }
 
         if (fromIndex == -1 && toIndex == getNumActiveViews() -1) {
@@ -216,63 +213,87 @@
             transformViewAtIndex(toIndex, view, false);
             view.setVisibility(VISIBLE);
 
-            alphaOa = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 1.0f);
-            alphaOa.setDuration(FADE_IN_ANIMATION_DURATION);
-            if (oldAlphaOa != null) oldAlphaOa.cancel();
-            alphaOa.start();
-            view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation,
-                    new WeakReference<ObjectAnimator>(alphaOa));
+            ((StackFrame) view).cancelAlphaAnimator();
+            if (animate) {
+                alphaOa = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 1.0f);
+                alphaOa.setDuration(FADE_IN_ANIMATION_DURATION);
+                ((StackFrame) view).setAlphaAnimator(alphaOa);
+                alphaOa.start();
+            } else {
+                view.setAlpha(1.0f);
+            }
         } else if (fromIndex == 0 && toIndex == 1) {
             // Slide item in
+            ((StackFrame) view).cancelSliderAnimator();
             view.setVisibility(VISIBLE);
 
             int duration = Math.round(mStackSlider.getDurationForNeutralPosition(mYVelocity));
-
             StackSlider animationSlider = new StackSlider(mStackSlider);
             animationSlider.setView(view);
-            PropertyValuesHolder slideInY = PropertyValuesHolder.ofFloat("YProgress", 0.0f);
-            PropertyValuesHolder slideInX = PropertyValuesHolder.ofFloat("XProgress", 0.0f);
-            ObjectAnimator slideIn = ObjectAnimator.ofPropertyValuesHolder(animationSlider,
-                    slideInX, slideInY);
-            slideIn.setDuration(duration);
-            slideIn.setInterpolator(new LinearInterpolator());
-            slideIn.start();
+
+            if (animate) {
+                PropertyValuesHolder slideInY = PropertyValuesHolder.ofFloat("YProgress", 0.0f);
+                PropertyValuesHolder slideInX = PropertyValuesHolder.ofFloat("XProgress", 0.0f);
+                ObjectAnimator slideIn = ObjectAnimator.ofPropertyValuesHolder(animationSlider,
+                        slideInX, slideInY);
+                slideIn.setDuration(duration);
+                slideIn.setInterpolator(new LinearInterpolator());
+                ((StackFrame) view).setSliderAnimator(slideIn);
+                slideIn.start();
+            } else {
+                animationSlider.setYProgress(0f);
+                animationSlider.setXProgress(0f);
+            }
         } else if (fromIndex == 1 && toIndex == 0) {
             // Slide item out
+            ((StackFrame) view).cancelSliderAnimator();
             int duration = Math.round(mStackSlider.getDurationForOffscreenPosition(mYVelocity));
 
             StackSlider animationSlider = new StackSlider(mStackSlider);
             animationSlider.setView(view);
-            PropertyValuesHolder slideOutY = PropertyValuesHolder.ofFloat("YProgress", 1.0f);
-            PropertyValuesHolder slideOutX = PropertyValuesHolder.ofFloat("XProgress", 0.0f);
-            ObjectAnimator slideOut = ObjectAnimator.ofPropertyValuesHolder(animationSlider,
-                    slideOutX, slideOutY);
-            slideOut.setDuration(duration);
-            slideOut.setInterpolator(new LinearInterpolator());
-            slideOut.start();
+            if (animate) {
+                PropertyValuesHolder slideOutY = PropertyValuesHolder.ofFloat("YProgress", 1.0f);
+                PropertyValuesHolder slideOutX = PropertyValuesHolder.ofFloat("XProgress", 0.0f);
+                ObjectAnimator slideOut = ObjectAnimator.ofPropertyValuesHolder(animationSlider,
+                        slideOutX, slideOutY);
+                slideOut.setDuration(duration);
+                slideOut.setInterpolator(new LinearInterpolator());
+                ((StackFrame) view).setSliderAnimator(slideOut);
+                slideOut.start();
+            } else {
+                animationSlider.setYProgress(1.0f);
+                animationSlider.setXProgress(0f);
+            }
         } else if (toIndex == 0) {
             // Make sure this view that is "waiting in the wings" is invisible
             view.setAlpha(0.0f);
             view.setVisibility(INVISIBLE);
-        } else if (fromIndex == 0 && toIndex > 1) {
+        } else if ((fromIndex == 0 || fromIndex == 1) && toIndex > 1) {
             view.setVisibility(VISIBLE);
             view.setAlpha(1.0f);
+            view.setRotationX(0f);
+            LayoutParams lp = (LayoutParams) view.getLayoutParams();
+            lp.setVerticalOffset(0);
+            lp.setHorizontalOffset(0);
         } else if (fromIndex == -1) {
             view.setAlpha(1.0f);
             view.setVisibility(VISIBLE);
         } else if (toIndex == -1) {
             // Fade item out
-            alphaOa = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 0.0f);
-            alphaOa.setDuration(STACK_RELAYOUT_DURATION);
-            if (oldAlphaOa != null) oldAlphaOa.cancel();
-            alphaOa.start();
-            view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation,
-                    new WeakReference<ObjectAnimator>(alphaOa));
+            ((StackFrame) view).cancelAlphaAnimator();
+            if (animate) {
+                alphaOa = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 0.0f);
+                alphaOa.setDuration(STACK_RELAYOUT_DURATION);
+                ((StackFrame) view).setAlphaAnimator(alphaOa);
+                alphaOa.start();
+            } else {
+                view.setAlpha(0f);
+            }
         }
 
         // Implement the faked perspective
         if (toIndex != -1) {
-            transformViewAtIndex(toIndex, view, true);
+            transformViewAtIndex(toIndex, view, animate);
         }
     }
 
@@ -304,12 +325,8 @@
 
         // If this view is currently being animated for a certain position, we need to cancel
         // this animation so as not to interfere with the new transformation.
-        Object tag = view.getTag(com.android.internal.R.id.viewAnimation);
-        if (tag instanceof WeakReference<?>) {
-            Object obj = ((WeakReference<?>) tag).get();
-            if (obj instanceof ObjectAnimator) {
-                ((ObjectAnimator) obj).cancel();
-            }
+        if (view instanceof StackFrame) {
+            ((StackFrame) view).cancelTransformAnimator();
         }
 
         if (animate) {
@@ -321,8 +338,9 @@
             ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(view, scalePropX, scalePropY,
                     translationY, translationX);
             oa.setDuration(STACK_RELAYOUT_DURATION);
-            view.setTagInternal(com.android.internal.R.id.viewAnimation, 
-                    new WeakReference<ObjectAnimator>(oa));
+            if (view instanceof StackFrame) {
+                ((StackFrame) view).setTransformAnimator(oa);
+            }
             oa.start();
         } else {
             view.setTranslationX(transX);
@@ -396,6 +414,9 @@
                 if (v != null) v.bringToFront();
             }
         }
+        if (mHighlight != null) {
+            mHighlight.bringToFront();
+        }
         mTransitionIsSetup = false;
         mClickFeedbackIsValid = false;
     }
@@ -436,9 +457,64 @@
         }
     }
 
+    private static class StackFrame extends FrameLayout {
+        WeakReference<ObjectAnimator> alphaAnimator;
+        WeakReference<ObjectAnimator> transformAnimator;
+        WeakReference<ObjectAnimator> sliderAnimator;
+
+        public StackFrame(Context context) {
+            super(context);
+        }
+
+        void setAlphaAnimator(ObjectAnimator oa) {
+            alphaAnimator = new WeakReference<ObjectAnimator>(oa);
+        }
+
+        void setTransformAnimator(ObjectAnimator oa) {
+            transformAnimator = new WeakReference<ObjectAnimator>(oa);
+        }
+
+        void setSliderAnimator(ObjectAnimator oa) {
+            sliderAnimator = new WeakReference<ObjectAnimator>(oa);
+        }
+
+        boolean cancelAlphaAnimator() {
+            if (alphaAnimator != null) {
+                ObjectAnimator oa = alphaAnimator.get();
+                if (oa != null) {
+                    oa.cancel();
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        boolean cancelTransformAnimator() {
+            if (transformAnimator != null) {
+                ObjectAnimator oa = transformAnimator.get();
+                if (oa != null) {
+                    oa.cancel();
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        boolean cancelSliderAnimator() {
+            if (sliderAnimator != null) {
+                ObjectAnimator oa = sliderAnimator.get();
+                if (oa != null) {
+                    oa.cancel();
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
     @Override
     FrameLayout getFrameForChild() {
-        FrameLayout fl = new FrameLayout(mContext);
+        StackFrame fl = new StackFrame(mContext);
         fl.setPadding(mFramePadding, mFramePadding, mFramePadding, mFramePadding);
         return fl;
     }
@@ -471,16 +547,26 @@
     private void onLayout() {
         if (!mFirstLayoutHappened) {
             mSlideAmount = Math.round(SLIDE_UP_RATIO * getMeasuredHeight());
-            updateChildTransforms();
             mSwipeThreshold = Math.round(SWIPE_THRESHOLD_RATIO * mSlideAmount);
             mFirstLayoutHappened = true;
+            post(new Runnable() {
+                public void run() {
+                    updateChildTransforms();
+                }
+            });
         }
 
         if (Float.compare(mPerspectiveShiftY, mNewPerspectiveShiftY) != 0 ||
                 Float.compare(mPerspectiveShiftX, mNewPerspectiveShiftX) != 0) {
+
             mPerspectiveShiftY = mNewPerspectiveShiftY;
             mPerspectiveShiftX = mNewPerspectiveShiftX;
-            updateChildTransforms();
+
+            post(new Runnable() {
+                public void run() {
+                    updateChildTransforms();
+                }
+            });
         }
     }
 
@@ -1034,11 +1120,11 @@
 
         mNewPerspectiveShiftX = PERSPECTIVE_SHIFT_FACTOR_X * measuredWidth;
         mNewPerspectiveShiftY = PERSPECTIVE_SHIFT_FACTOR_Y * measuredHeight;
-        if (maxWidth > 0 && maxWidth < childWidth) {
+        if (maxWidth > 0 && count > 0 && maxWidth < childWidth) {
             mNewPerspectiveShiftX = measuredWidth - maxWidth;
         }
 
-        if (maxHeight > 0 && maxHeight < childHeight) {
+        if (maxHeight > 0 && count > 0 && maxHeight < childHeight) {
             mNewPerspectiveShiftY = measuredHeight - maxHeight;
         }
     }
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index 837e04f..7a0fede 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -73,6 +73,4 @@
   <item type="id" name="fillInIntent" />
   <item type="id" name="rowTypeId" />
   <item type="id" name="up" />
-  <item type="id" name="viewAnimation" />
-  <item type="id" name="viewAlphaAnimation" />
 </resources>