Merge "Make fragment animations work when fragments go away"
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index 052a38a..0310a31 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -42,7 +42,7 @@
* @attr ref android.R.styleable#AdapterViewAnimator_animateFirstView
*/
public abstract class AdapterViewAnimator extends AdapterView<Adapter>
- implements RemoteViewsAdapter.RemoteAdapterConnectionCallback{
+ implements RemoteViewsAdapter.RemoteAdapterConnectionCallback {
private static final String TAG = "RemoteViewAnimator";
/**
@@ -358,6 +358,17 @@
}
}
+ /**
+ * 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.
+ */
+ FrameLayout getFrameForChild() {
+ return new FrameLayout(mContext);
+ }
+
void showOnly(int childIndex, boolean animate, boolean onLayout) {
if (mAdapter == null) return;
@@ -436,7 +447,7 @@
// 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 = new FrameLayout(mContext);
+ FrameLayout fl = getFrameForChild();
// If the view from the adapter is null, we still keep an empty frame in place
if (newView != null) {
diff --git a/core/java/android/widget/NumberPickerButton.java b/core/java/android/widget/NumberPickerButton.java
index 1c8579c..292b668 100644
--- a/core/java/android/widget/NumberPickerButton.java
+++ b/core/java/android/widget/NumberPickerButton.java
@@ -85,4 +85,12 @@
mNumberPicker.cancelDecrement();
}
}
+
+ public void onWindowFocusChanged(boolean hasWindowFocus) {
+ super.onWindowFocusChanged(hasWindowFocus);
+ if (!hasWindowFocus) {
+ cancelLongpress();
+ }
+ }
+
}
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 2aa0bc6..0f1acbe 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -19,6 +19,7 @@
import android.animation.PropertyValuesHolder;
import android.animation.ObjectAnimator;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
@@ -30,6 +31,7 @@
import android.graphics.RectF;
import android.graphics.TableMaskFilter;
import android.util.AttributeSet;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
@@ -93,6 +95,7 @@
*/
private static final int NUM_ACTIVE_VIEWS = 5;
+ private static final int FRAME_PADDING = 4;
/**
* These variables are all related to the current state of touch interaction
@@ -103,7 +106,7 @@
private int mActivePointerId;
private int mYVelocity = 0;
private int mSwipeGestureType = GESTURE_NONE;
- private int mViewHeight;
+ private int mSlideAmount;
private int mSwipeThreshold;
private int mTouchSlop;
private int mMaximumVelocity;
@@ -116,6 +119,7 @@
private ViewGroup mAncestorContainingAllChildren = null;
private int mAncestorHeight = 0;
private int mStackMode;
+ private int mFramePadding;
public StackView(Context context) {
super(context);
@@ -141,7 +145,7 @@
mStackSlider = new StackSlider();
if (sHolographicHelper == null) {
- sHolographicHelper = new HolographicHelper();
+ sHolographicHelper = new HolographicHelper(mContext);
}
setClipChildren(false);
setClipToPadding(false);
@@ -153,6 +157,11 @@
// This is a flag to indicate the the stack is loading for the first time
mWhichChild = -1;
+
+ // Adjust the frame padding based on the density, since the highlight changes based
+ // on the density
+ final float density = mContext.getResources().getDisplayMetrics().density;
+ mFramePadding = (int) Math.ceil(density * FRAME_PADDING);
}
/**
@@ -205,7 +214,7 @@
view.setAlpha(0.0f);
view.setVisibility(INVISIBLE);
LayoutParams lp = (LayoutParams) view.getLayoutParams();
- lp.setVerticalOffset(-mViewHeight);
+ lp.setVerticalOffset(-mSlideAmount);
} else if (toIndex == -1) {
// Fade item out
ObjectAnimator<Float> fadeOut = new ObjectAnimator<Float>
@@ -220,7 +229,7 @@
}
private void transformViewAtIndex(int index, View view) {
- float maxPerpectiveShift = mViewHeight * PERSPECTIVE_SHIFT_FACTOR;
+ float maxPerpectiveShift = mMeasuredHeight * PERSPECTIVE_SHIFT_FACTOR;
if (index == mNumActiveViews -1) index--;
@@ -233,8 +242,10 @@
r = (float) Math.pow(r, 2);
int stackDirection = (mStackMode == ITEMS_SLIDE_UP) ? 1 : -1;
- float transY = -stackDirection * r * maxPerpectiveShift +
- stackDirection * (1 - scale) * (mViewHeight / 2.0f);
+ float perspectiveTranslation = -stackDirection * r * maxPerpectiveShift;
+ float scaleShiftCorrection = stackDirection * (1 - scale) *
+ (mMeasuredHeight * (1 - PERSPECTIVE_SHIFT_FACTOR) / 2.0f);
+ float transY = perspectiveTranslation + scaleShiftCorrection;
PropertyValuesHolder<Float> translationY =
new PropertyValuesHolder<Float>("translationY", transY);
@@ -251,6 +262,13 @@
}
}
+ @Override
+ FrameLayout getFrameForChild() {
+ FrameLayout fl = new FrameLayout(mContext);
+ fl.setPadding(mFramePadding, mFramePadding, mFramePadding, mFramePadding);
+ return fl;
+ }
+
/**
* Apply any necessary tranforms for the child that is being added.
*/
@@ -282,9 +300,9 @@
private void onLayout() {
if (!mFirstLayoutHappened) {
- mViewHeight = Math.round(SLIDE_UP_RATIO * getMeasuredHeight());
+ mSlideAmount = Math.round(SLIDE_UP_RATIO * getMeasuredHeight());
updateChildTransforms();
- mSwipeThreshold = Math.round(SWIPE_THRESHOLD_RATIO * mViewHeight);
+ mSwipeThreshold = Math.round(SWIPE_THRESHOLD_RATIO * mSlideAmount);
mFirstLayoutHappened = true;
}
}
@@ -395,15 +413,15 @@
case MotionEvent.ACTION_MOVE: {
beginGestureIfNeeded(deltaY);
- float rx = deltaX / (mViewHeight * 1.0f);
+ float rx = deltaX / (mSlideAmount * 1.0f);
if (mSwipeGestureType == GESTURE_SLIDE_DOWN) {
- float r = (deltaY - mTouchSlop * 1.0f) / mViewHeight * 1.0f;
+ float r = (deltaY - mTouchSlop * 1.0f) / mSlideAmount * 1.0f;
if (mStackMode == ITEMS_SLIDE_DOWN) r = 1 - r;
mStackSlider.setYProgress(1 - r);
mStackSlider.setXProgress(rx);
return true;
} else if (mSwipeGestureType == GESTURE_SLIDE_UP) {
- float r = -(deltaY + mTouchSlop * 1.0f) / mViewHeight * 1.0f;
+ float r = -(deltaY + mTouchSlop * 1.0f) / mSlideAmount * 1.0f;
if (mStackMode == ITEMS_SLIDE_DOWN) r = 1 - r;
mStackSlider.setYProgress(r);
mStackSlider.setXProgress(rx);
@@ -620,8 +638,8 @@
switch (mMode) {
case NORMAL_MODE:
- viewLp.setVerticalOffset(Math.round(-r * stackDirection * mViewHeight));
- highlightLp.setVerticalOffset(Math.round(-r * stackDirection * mViewHeight));
+ viewLp.setVerticalOffset(Math.round(-r * stackDirection * mSlideAmount));
+ highlightLp.setVerticalOffset(Math.round(-r * stackDirection * mSlideAmount));
mHighlight.setAlpha(highlightAlphaInterpolator(r));
float alpha = viewAlphaInterpolator(1 - r);
@@ -641,14 +659,14 @@
break;
case BEGINNING_OF_STACK_MODE:
r = r * 0.2f;
- viewLp.setVerticalOffset(Math.round(-stackDirection * r * mViewHeight));
- highlightLp.setVerticalOffset(Math.round(-stackDirection * r * mViewHeight));
+ viewLp.setVerticalOffset(Math.round(-stackDirection * r * mSlideAmount));
+ highlightLp.setVerticalOffset(Math.round(-stackDirection * r * mSlideAmount));
mHighlight.setAlpha(highlightAlphaInterpolator(r));
break;
case END_OF_STACK_MODE:
r = (1-r) * 0.2f;
- viewLp.setVerticalOffset(Math.round(stackDirection * r * mViewHeight));
- highlightLp.setVerticalOffset(Math.round(stackDirection * r * mViewHeight));
+ viewLp.setVerticalOffset(Math.round(stackDirection * r * mSlideAmount));
+ highlightLp.setVerticalOffset(Math.round(stackDirection * r * mSlideAmount));
mHighlight.setAlpha(highlightAlphaInterpolator(r));
break;
}
@@ -665,8 +683,8 @@
final LayoutParams highlightLp = (LayoutParams) mHighlight.getLayoutParams();
r *= 0.2f;
- viewLp.setHorizontalOffset(Math.round(r * mViewHeight));
- highlightLp.setHorizontalOffset(Math.round(r * mViewHeight));
+ viewLp.setHorizontalOffset(Math.round(r * mSlideAmount));
+ highlightLp.setHorizontalOffset(Math.round(r * mSlideAmount));
}
void setMode(int mode) {
@@ -695,8 +713,8 @@
float d = (float) Math.sqrt(Math.pow(viewLp.horizontalOffset, 2) +
Math.pow(viewLp.verticalOffset, 2));
- float maxd = (float) Math.sqrt(Math.pow(mViewHeight, 2) +
- Math.pow(0.4f * mViewHeight, 2));
+ float maxd = (float) Math.sqrt(Math.pow(mSlideAmount, 2) +
+ Math.pow(0.4f * mSlideAmount, 2));
if (velocity == 0) {
return (invert ? (1 - d / maxd) : d / maxd) * DEFAULT_ANIMATION_DURATION;
@@ -940,17 +958,19 @@
private final Paint mErasePaint = new Paint();
private final Paint mBlurPaint = new Paint();
- HolographicHelper() {
- initializePaints();
+ HolographicHelper(Context context) {
+ initializePaints(context);
}
- void initializePaints() {
+ void initializePaints(Context context) {
+ final float density = context.getResources().getDisplayMetrics().density;
+
mHolographicPaint.setColor(0xff6699ff);
mHolographicPaint.setFilterBitmap(true);
mHolographicPaint.setMaskFilter(TableMaskFilter.CreateClipTable(0, 30));
mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
mErasePaint.setFilterBitmap(true);
- mBlurPaint.setMaskFilter(new BlurMaskFilter(2, BlurMaskFilter.Blur.NORMAL));
+ mBlurPaint.setMaskFilter(new BlurMaskFilter(2*density, BlurMaskFilter.Blur.NORMAL));
}
Bitmap createOutline(View v) {
@@ -968,12 +988,10 @@
v.setRotationX(0);
v.setRotation(0);
v.setTranslationY(0);
- canvas.concat(v.getMatrix());
v.draw(canvas);
v.setRotationX(rotationX);
v.setRotation(rotation);
v.setTranslationY(translationY);
- canvas.setMatrix(id);
drawOutline(canvas, bitmap);
return bitmap;