1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.systemui.statusbar.notification; 18 19 import android.graphics.drawable.Icon; 20 import android.util.Pools; 21 import android.view.View; 22 import android.widget.ImageView; 23 24 import com.android.app.animation.Interpolators; 25 import com.android.systemui.res.R; 26 import com.android.systemui.statusbar.CrossFadeHelper; 27 import com.android.systemui.statusbar.TransformableView; 28 import com.android.systemui.statusbar.notification.row.HybridNotificationView; 29 import com.android.systemui.statusbar.notification.stack.StackStateAnimator; 30 31 /** 32 * A transform state of a image view. 33 */ 34 public class ImageTransformState extends TransformState { 35 public static final long ANIMATION_DURATION_LENGTH = 210; 36 37 public static final int ICON_TAG = R.id.image_icon_tag; 38 private static Pools.SimplePool<ImageTransformState> sInstancePool 39 = new Pools.SimplePool<>(40); 40 private Icon mIcon; 41 42 @Override initFrom(View view, TransformInfo transformInfo)43 public void initFrom(View view, TransformInfo transformInfo) { 44 super.initFrom(view, transformInfo); 45 if (view instanceof ImageView) { 46 mIcon = (Icon) view.getTag(ICON_TAG); 47 } 48 } 49 50 @Override sameAs(TransformState otherState)51 protected boolean sameAs(TransformState otherState) { 52 if (super.sameAs(otherState)) { 53 return true; 54 } 55 if (otherState instanceof ImageTransformState) { 56 final Icon otherIcon = ((ImageTransformState) otherState).mIcon; 57 return mIcon == otherIcon || (mIcon != null && otherIcon != null && mIcon.sameAs( 58 otherIcon)); 59 } 60 return false; 61 } 62 63 @Override appear(float transformationAmount, TransformableView otherView)64 public void appear(float transformationAmount, TransformableView otherView) { 65 if (otherView instanceof HybridNotificationView) { 66 if (transformationAmount == 0.0f) { 67 mTransformedView.setPivotY(0); 68 mTransformedView.setPivotX(mTransformedView.getWidth() / 2); 69 prepareFadeIn(); 70 } 71 transformationAmount = mapToDuration(transformationAmount); 72 CrossFadeHelper.fadeIn(mTransformedView, transformationAmount, false /* remap */); 73 transformationAmount = Interpolators.LINEAR_OUT_SLOW_IN.getInterpolation( 74 transformationAmount); 75 mTransformedView.setScaleX(transformationAmount); 76 mTransformedView.setScaleY(transformationAmount); 77 } else { 78 super.appear(transformationAmount, otherView); 79 } 80 } 81 82 @Override disappear(float transformationAmount, TransformableView otherView)83 public void disappear(float transformationAmount, TransformableView otherView) { 84 if (otherView instanceof HybridNotificationView) { 85 if (transformationAmount == 0.0f) { 86 mTransformedView.setPivotY(0); 87 mTransformedView.setPivotX(mTransformedView.getWidth() / 2); 88 } 89 transformationAmount = mapToDuration(1.0f - transformationAmount); 90 CrossFadeHelper.fadeOut(mTransformedView, 1.0f - transformationAmount, 91 false /* remap */); 92 transformationAmount = Interpolators.LINEAR_OUT_SLOW_IN.getInterpolation( 93 transformationAmount); 94 mTransformedView.setScaleX(transformationAmount); 95 mTransformedView.setScaleY(transformationAmount); 96 } else { 97 super.disappear(transformationAmount, otherView); 98 } 99 } 100 mapToDuration(float scaleAmount)101 private static float mapToDuration(float scaleAmount) { 102 // Assuming a linear interpolator, we can easily map it to our new duration 103 scaleAmount = (scaleAmount * StackStateAnimator.ANIMATION_DURATION_STANDARD 104 - (StackStateAnimator.ANIMATION_DURATION_STANDARD - ANIMATION_DURATION_LENGTH)) 105 / ANIMATION_DURATION_LENGTH; 106 return Math.max(Math.min(scaleAmount, 1.0f), 0.0f); 107 } 108 getIcon()109 public Icon getIcon() { 110 return mIcon; 111 } 112 obtain()113 public static ImageTransformState obtain() { 114 ImageTransformState instance = sInstancePool.acquire(); 115 if (instance != null) { 116 return instance; 117 } 118 return new ImageTransformState(); 119 } 120 121 @Override recycle()122 public void recycle() { 123 super.recycle(); 124 if (getClass() == ImageTransformState.class) { 125 sInstancePool.release(this); 126 } 127 } 128 129 @Override reset()130 protected void reset() { 131 super.reset(); 132 mIcon = null; 133 } 134 } 135