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