1 /*
2  * Copyright (C) 2017 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.Drawable;
20 import android.util.FloatProperty;
21 import android.util.Log;
22 import android.util.Property;
23 import android.view.View;
24 
25 import com.android.systemui.R;
26 
27 import java.util.function.BiConsumer;
28 import java.util.function.Function;
29 
30 /**
31  * An animatable property of a view. Used with {@link PropertyAnimator}
32  */
33 public abstract class AnimatableProperty {
34 
35     public static final AnimatableProperty X = AnimatableProperty.from(View.X,
36             R.id.x_animator_tag, R.id.x_animator_tag_start_value, R.id.x_animator_tag_end_value);
37     public static final AnimatableProperty Y = AnimatableProperty.from(View.Y,
38             R.id.y_animator_tag, R.id.y_animator_tag_start_value, R.id.y_animator_tag_end_value);
39 
40     /**
41      * Similar to X, however this doesn't allow for any other modifications other than from this
42      * property. When using X, it's possible that the view is laid out during the animation,
43      * which could break the continuity
44      */
45     public static final AnimatableProperty ABSOLUTE_X = AnimatableProperty.from(
46             new FloatProperty<View>("ViewAbsoluteX") {
47                 @Override
48                 public void setValue(View view, float value) {
49                     view.setTag(R.id.absolute_x_current_value, value);
50                     View.X.set(view, value);
51                 }
52 
53                 @Override
54                 public Float get(View view) {
55                     Object tag = view.getTag(R.id.absolute_x_current_value);
56                     if (tag instanceof Float) {
57                         return (Float) tag;
58                     }
59                     return View.X.get(view);
60                 }
61             },
62             R.id.absolute_x_animator_tag,
63             R.id.absolute_x_animator_start_tag,
64             R.id.absolute_x_animator_end_tag);
65 
66     /**
67      * Similar to Y, however this doesn't allow for any other modifications other than from this
68      * property. When using X, it's possible that the view is laid out during the animation,
69      * which could break the continuity
70      */
71     public static final AnimatableProperty ABSOLUTE_Y = AnimatableProperty.from(
72             new FloatProperty<View>("ViewAbsoluteY") {
73                 @Override
74                 public void setValue(View view, float value) {
75                     view.setTag(R.id.absolute_y_current_value, value);
76                     View.Y.set(view, value);
77                 }
78 
79                 @Override
80                 public Float get(View view) {
81                     Object tag = view.getTag(R.id.absolute_y_current_value);
82                     if (tag instanceof Float) {
83                         return (Float) tag;
84                     }
85                     return View.Y.get(view);
86                 }
87             },
88             R.id.absolute_y_animator_tag,
89             R.id.absolute_y_animator_start_tag,
90             R.id.absolute_y_animator_end_tag);
91 
92     public static final AnimatableProperty WIDTH = AnimatableProperty.from(
93             new FloatProperty<View>("ViewWidth") {
94                 @Override
95                 public void setValue(View view, float value) {
96                     view.setTag(R.id.view_width_current_value, value);
97                     view.setRight((int) (view.getLeft() + value));
98                 }
99 
100                 @Override
101                 public Float get(View view) {
102                     Object tag = view.getTag(R.id.view_width_current_value);
103                     if (tag instanceof Float) {
104                         return (Float) tag;
105                     }
106                     return (float) view.getWidth();
107                 }
108             },
109             R.id.view_width_animator_tag,
110             R.id.view_width_animator_start_tag,
111             R.id.view_width_animator_end_tag);
112 
113     public static final AnimatableProperty HEIGHT = AnimatableProperty.from(
114             new FloatProperty<View>("ViewHeight") {
115                 @Override
116                 public void setValue(View view, float value) {
117                     view.setTag(R.id.view_height_current_value, value);
118                     view.setBottom((int) (view.getTop() + value));
119                 }
120 
121                 @Override
122                 public Float get(View view) {
123                     Object tag = view.getTag(R.id.view_height_current_value);
124                     if (tag instanceof Float) {
125                         return (Float) tag;
126                     }
127                     return (float) view.getHeight();
128                 }
129             },
130             R.id.view_height_animator_tag,
131             R.id.view_height_animator_start_tag,
132             R.id.view_height_animator_end_tag);
133 
getAnimationStartTag()134     public abstract int getAnimationStartTag();
135 
getAnimationEndTag()136     public abstract int getAnimationEndTag();
137 
getAnimatorTag()138     public abstract int getAnimatorTag();
139 
getProperty()140     public abstract Property getProperty();
141 
from(String name, BiConsumer<T, Float> setter, Function<T, Float> getter, int animatorTag, int startValueTag, int endValueTag)142     public static <T extends View> AnimatableProperty from(String name, BiConsumer<T, Float> setter,
143             Function<T, Float> getter, int animatorTag, int startValueTag, int endValueTag) {
144         Property<T, Float> property = new FloatProperty<T>(name) {
145 
146             @Override
147             public Float get(T object) {
148                 return getter.apply(object);
149             }
150 
151             @Override
152             public void setValue(T object, float value) {
153                 setter.accept(object, value);
154             }
155         };
156         return new AnimatableProperty() {
157             @Override
158             public int getAnimationStartTag() {
159                 return startValueTag;
160             }
161 
162             @Override
163             public int getAnimationEndTag() {
164                 return endValueTag;
165             }
166 
167             @Override
168             public int getAnimatorTag() {
169                 return animatorTag;
170             }
171 
172             @Override
173             public Property getProperty() {
174                 return property;
175             }
176         };
177     }
178 
179     public static <T extends View> AnimatableProperty from(Property<T, Float> property,
180             int animatorTag, int startValueTag, int endValueTag) {
181         return new AnimatableProperty() {
182             @Override
183             public int getAnimationStartTag() {
184                 return startValueTag;
185             }
186 
187             @Override
188             public int getAnimationEndTag() {
189                 return endValueTag;
190             }
191 
192             @Override
193             public int getAnimatorTag() {
194                 return animatorTag;
195             }
196 
197             @Override
198             public Property getProperty() {
199                 return property;
200             }
201         };
202     }
203 }
204