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.systemui.Interpolators; 25 import com.android.systemui.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 return mIcon != null && mIcon.sameAs(((ImageTransformState) otherState).getIcon()); 57 } 58 return false; 59 } 60 61 @Override appear(float transformationAmount, TransformableView otherView)62 public void appear(float transformationAmount, TransformableView otherView) { 63 if (otherView instanceof HybridNotificationView) { 64 if (transformationAmount == 0.0f) { 65 mTransformedView.setPivotY(0); 66 mTransformedView.setPivotX(mTransformedView.getWidth() / 2); 67 prepareFadeIn(); 68 } 69 transformationAmount = mapToDuration(transformationAmount); 70 CrossFadeHelper.fadeIn(mTransformedView, transformationAmount, false /* remap */); 71 transformationAmount = Interpolators.LINEAR_OUT_SLOW_IN.getInterpolation( 72 transformationAmount); 73 mTransformedView.setScaleX(transformationAmount); 74 mTransformedView.setScaleY(transformationAmount); 75 } else { 76 super.appear(transformationAmount, otherView); 77 } 78 } 79 80 @Override disappear(float transformationAmount, TransformableView otherView)81 public void disappear(float transformationAmount, TransformableView otherView) { 82 if (otherView instanceof HybridNotificationView) { 83 if (transformationAmount == 0.0f) { 84 mTransformedView.setPivotY(0); 85 mTransformedView.setPivotX(mTransformedView.getWidth() / 2); 86 } 87 transformationAmount = mapToDuration(1.0f - transformationAmount); 88 CrossFadeHelper.fadeOut(mTransformedView, 1.0f - transformationAmount, 89 false /* remap */); 90 transformationAmount = Interpolators.LINEAR_OUT_SLOW_IN.getInterpolation( 91 transformationAmount); 92 mTransformedView.setScaleX(transformationAmount); 93 mTransformedView.setScaleY(transformationAmount); 94 } else { 95 super.disappear(transformationAmount, otherView); 96 } 97 } 98 mapToDuration(float scaleAmount)99 private static float mapToDuration(float scaleAmount) { 100 // Assuming a linear interpolator, we can easily map it to our new duration 101 scaleAmount = (scaleAmount * StackStateAnimator.ANIMATION_DURATION_STANDARD 102 - (StackStateAnimator.ANIMATION_DURATION_STANDARD - ANIMATION_DURATION_LENGTH)) 103 / ANIMATION_DURATION_LENGTH; 104 return Math.max(Math.min(scaleAmount, 1.0f), 0.0f); 105 } 106 getIcon()107 public Icon getIcon() { 108 return mIcon; 109 } 110 obtain()111 public static ImageTransformState obtain() { 112 ImageTransformState instance = sInstancePool.acquire(); 113 if (instance != null) { 114 return instance; 115 } 116 return new ImageTransformState(); 117 } 118 119 @Override transformScale(TransformState otherState)120 protected boolean transformScale(TransformState otherState) { 121 return sameAs(otherState); 122 } 123 124 @Override recycle()125 public void recycle() { 126 super.recycle(); 127 if (getClass() == ImageTransformState.class) { 128 sInstancePool.release(this); 129 } 130 } 131 132 @Override reset()133 protected void reset() { 134 super.reset(); 135 mIcon = null; 136 } 137 } 138