diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java index 123dc699e5930..e8f0925dcc711 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CrossFadeHelper.java @@ -48,13 +48,30 @@ public class CrossFadeHelper { } public static void fadeOut(View view, float fadeOutAmount) { + fadeOut(view, fadeOutAmount, true /* remap */); + } + + /** + * Fade out a view by a given progress amount + * @param view the view to fade out + * @param fadeOutAmount how much the view is faded out. 0 means not at all and 1 means fully + * faded out + * @param remap whether the fade amount should be remapped to the shorter duration + * {@link #ANIMATION_DURATION_LENGTH} from the normal fade duration + * {@link StackStateAnimator#ANIMATION_DURATION_STANDARD} in order to have a faster fading. + * + * @see #fadeIn(View, float, boolean) + */ + public static void fadeOut(View view, float fadeOutAmount, boolean remap) { view.animate().cancel(); if (fadeOutAmount == 1.0f) { view.setVisibility(View.INVISIBLE); } else if (view.getVisibility() == View.INVISIBLE) { view.setVisibility(View.VISIBLE); } - fadeOutAmount = mapToFadeDuration(fadeOutAmount); + if (remap) { + fadeOutAmount = mapToFadeDuration(fadeOutAmount); + } float alpha = Interpolators.ALPHA_OUT.getInterpolation(1.0f - fadeOutAmount); view.setAlpha(alpha); updateLayerType(view, alpha); @@ -92,11 +109,28 @@ public class CrossFadeHelper { } public static void fadeIn(View view, float fadeInAmount) { + fadeIn(view, fadeInAmount, true /* remap */); + } + + /** + * Fade in a view by a given progress amount + * @param view the view to fade in + * @param fadeInAmount how much the view is faded in. 0 means not at all and 1 means fully + * faded in. + * @param remap whether the fade amount should be remapped to the shorter duration + * {@link #ANIMATION_DURATION_LENGTH} from the normal fade duration + * {@link StackStateAnimator#ANIMATION_DURATION_STANDARD} in order to have a faster fading. + * + * @see #fadeOut(View, float, boolean) + */ + public static void fadeIn(View view, float fadeInAmount, boolean remap) { view.animate().cancel(); if (view.getVisibility() == View.INVISIBLE) { view.setVisibility(View.VISIBLE); } - fadeInAmount = mapToFadeDuration(fadeInAmount); + if (remap) { + fadeInAmount = mapToFadeDuration(fadeInAmount); + } float alpha = Interpolators.ALPHA_IN.getInterpolation(fadeInAmount); view.setAlpha(alpha); updateLayerType(view, alpha); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java index 1ff2b1328464b..cd6c31f370d32 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/ViewTransformationHelper.java @@ -116,8 +116,7 @@ public class ViewTransformationHelper implements TransformableView { ownState.transformViewTo(otherState, transformationAmount); otherState.recycle(); } else { - // there's no other view available - CrossFadeHelper.fadeOut(mTransformedViews.get(viewType), transformationAmount); + ownState.disappear(transformationAmount, notification); } ownState.recycle(); } @@ -174,13 +173,7 @@ public class ViewTransformationHelper implements TransformableView { ownState.transformViewFrom(otherState, transformationAmount); otherState.recycle(); } else { - // There's no other view, lets fade us in - // Certain views need to prepare the fade in and make sure its children are - // completely visible. An example is the notification header. - if (transformationAmount == 0.0f) { - ownState.prepareFadeIn(); - } - CrossFadeHelper.fadeIn(mTransformedViews.get(viewType), transformationAmount); + ownState.appear(transformationAmount, notification); } ownState.recycle(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java index 45027c0dba7ee..e6b3fb86abe48 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ImageTransformState.java @@ -21,12 +21,17 @@ import android.util.Pools; import android.view.View; import android.widget.ImageView; +import com.android.systemui.Interpolators; import com.android.systemui.R; +import com.android.systemui.statusbar.CrossFadeHelper; +import com.android.systemui.statusbar.TransformableView; +import com.android.systemui.statusbar.stack.StackStateAnimator; /** * A transform state of a image view. */ public class ImageTransformState extends TransformState { + public static final long ANIMATION_DURATION_LENGTH = 210; public static final int ICON_TAG = R.id.image_icon_tag; private static Pools.SimplePool sInstancePool @@ -49,6 +54,52 @@ public class ImageTransformState extends TransformState { return super.sameAs(otherState); } + @Override + public void appear(float transformationAmount, TransformableView otherView) { + if (otherView instanceof HybridNotificationView) { + if (transformationAmount == 0.0f) { + mTransformedView.setPivotY(0); + mTransformedView.setPivotX(mTransformedView.getWidth() / 2); + prepareFadeIn(); + } + transformationAmount = mapToDuration(transformationAmount); + CrossFadeHelper.fadeIn(mTransformedView, transformationAmount, false /* remap */); + transformationAmount = Interpolators.LINEAR_OUT_SLOW_IN.getInterpolation( + transformationAmount); + mTransformedView.setScaleX(transformationAmount); + mTransformedView.setScaleY(transformationAmount); + } else { + super.appear(transformationAmount, otherView); + } + } + + @Override + public void disappear(float transformationAmount, TransformableView otherView) { + if (otherView instanceof HybridNotificationView) { + if (transformationAmount == 0.0f) { + mTransformedView.setPivotY(0); + mTransformedView.setPivotX(mTransformedView.getWidth() / 2); + } + transformationAmount = mapToDuration(1.0f - transformationAmount); + CrossFadeHelper.fadeOut(mTransformedView, 1.0f - transformationAmount, + false /* remap */); + transformationAmount = Interpolators.LINEAR_OUT_SLOW_IN.getInterpolation( + transformationAmount); + mTransformedView.setScaleX(transformationAmount); + mTransformedView.setScaleY(transformationAmount); + } else { + super.disappear(transformationAmount, otherView); + } + } + + private static float mapToDuration(float scaleAmount) { + // Assuming a linear interpolator, we can easily map it to our new duration + scaleAmount = (scaleAmount * StackStateAnimator.ANIMATION_DURATION_STANDARD + - (StackStateAnimator.ANIMATION_DURATION_STANDARD - ANIMATION_DURATION_LENGTH)) + / ANIMATION_DURATION_LENGTH; + return Math.max(Math.min(scaleAmount, 1.0f), 0.0f); + } + public Icon getIcon() { return mIcon; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java index f0f5c8db18219..770ec950504a3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/TransformState.java @@ -30,6 +30,7 @@ import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.ExpandableNotificationRow; +import com.android.systemui.statusbar.TransformableView; import com.android.systemui.statusbar.ViewTransformationHelper; /** @@ -357,6 +358,7 @@ public class TransformState { public int[] getLaidOutLocationOnScreen() { int[] location = getLocationOnScreen(); + // remove translation location[0] -= mTransformedView.getTranslationX(); location[1] -= mTransformedView.getTranslationY(); return location; @@ -364,6 +366,10 @@ public class TransformState { public int[] getLocationOnScreen() { mTransformedView.getLocationOnScreen(mOwnPosition); + + // remove scale + mOwnPosition[0] -= (1.0f - mTransformedView.getScaleX()) * mTransformedView.getPivotX(); + mOwnPosition[1] -= (1.0f - mTransformedView.getScaleY()) * mTransformedView.getPivotY(); return mOwnPosition; } @@ -371,6 +377,20 @@ public class TransformState { return false; } + public void appear(float transformationAmount, TransformableView otherView) { + // There's no other view, lets fade us in + // Certain views need to prepare the fade in and make sure its children are + // completely visible. An example is the notification header. + if (transformationAmount == 0.0f) { + prepareFadeIn(); + } + CrossFadeHelper.fadeIn(mTransformedView, transformationAmount); + } + + public void disappear(float transformationAmount, TransformableView otherView) { + CrossFadeHelper.fadeOut(mTransformedView, transformationAmount); + } + public static TransformState createFrom(View view) { if (view instanceof TextView) { TextViewTransformState result = TextViewTransformState.obtain();