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