1 /*
2  * Copyright (C) 2020 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 package androidx.constraintlayout.motion.utils;
17 
18 import android.os.Build;
19 import android.util.Log;
20 import android.view.View;
21 
22 import androidx.constraintlayout.core.motion.utils.KeyCycleOscillator;
23 import androidx.constraintlayout.motion.widget.Key;
24 import androidx.constraintlayout.motion.widget.MotionLayout;
25 import androidx.constraintlayout.widget.ConstraintAttribute;
26 
27 import java.lang.reflect.InvocationTargetException;
28 import java.lang.reflect.Method;
29 
30 /**
31  * Provide the engine for executing cycles.
32  * KeyCycleOscillator
33  *
34  *
35  */
36 public abstract class ViewOscillator extends KeyCycleOscillator {
37     private static final String TAG = "ViewOscillator";
38 
39     /**
40      * Set the property of that view
41      * @param view
42      * @param t
43      */
setProperty(View view, float t)44     public abstract void setProperty(View view, float t);
45 
46     /**
47      * Create a spline that manipulates a specific property of a view
48      * @param str the property to manipulate
49      * @return
50      */
makeSpline(String str)51     public static ViewOscillator makeSpline(String str) {
52         if (str.startsWith(Key.CUSTOM)) {
53             return new CustomSet();
54         }
55         switch (str) {
56             case Key.ALPHA:
57                 return new AlphaSet();
58             case Key.ELEVATION:
59                 return new ElevationSet();
60             case Key.ROTATION:
61                 return new RotationSet();
62             case Key.ROTATION_X:
63                 return new RotationXset();
64             case Key.ROTATION_Y:
65                 return new RotationYset();
66             case Key.TRANSITION_PATH_ROTATE:
67                 return new PathRotateSet();
68             case Key.SCALE_X:
69                 return new ScaleXset();
70             case Key.SCALE_Y:
71                 return new ScaleYset();
72             case Key.WAVE_OFFSET:
73                 return new AlphaSet();
74             case Key.WAVE_VARIES_BY:
75                 return new AlphaSet();
76             case Key.TRANSLATION_X:
77                 return new TranslationXset();
78             case Key.TRANSLATION_Y:
79                 return new TranslationYset();
80             case Key.TRANSLATION_Z:
81                 return new TranslationZset();
82             case Key.PROGRESS:
83                 return new ProgressSet();
84             default:
85                 return null;
86         }
87     }
88 
89     static class ElevationSet extends ViewOscillator {
90         @Override
setProperty(View view, float t)91         public void setProperty(View view, float t) {
92             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
93                 view.setElevation(get(t));
94             }
95         }
96     }
97 
98     static class AlphaSet extends ViewOscillator {
99         @Override
setProperty(View view, float t)100         public void setProperty(View view, float t) {
101             view.setAlpha(get(t));
102         }
103     }
104 
105     static class RotationSet extends ViewOscillator {
106         @Override
setProperty(View view, float t)107         public void setProperty(View view, float t) {
108             view.setRotation(get(t));
109         }
110     }
111 
112     static class RotationXset extends ViewOscillator {
113         @Override
setProperty(View view, float t)114         public void setProperty(View view, float t) {
115             view.setRotationX(get(t));
116         }
117     }
118 
119     static class RotationYset extends ViewOscillator {
120         @Override
setProperty(View view, float t)121         public void setProperty(View view, float t) {
122             view.setRotationY(get(t));
123         }
124     }
125 
126     public static class PathRotateSet extends ViewOscillator {
127         @Override
setProperty(View view, float t)128         public void setProperty(View view, float t) {
129         }
130 
131         /**
132          *  use to modify the rotation relative to the current path
133          * @param view the view to modify
134          * @param t the point in time to manipulate
135          * @param dx of the path
136          * @param dy of the path
137          */
setPathRotate(View view, float t, double dx, double dy)138         public void setPathRotate(View view, float t, double dx, double dy) {
139             view.setRotation(get(t) + (float) Math.toDegrees(Math.atan2(dy, dx)));
140         }
141     }
142 
143     static class ScaleXset extends ViewOscillator {
144         @Override
setProperty(View view, float t)145         public void setProperty(View view, float t) {
146             view.setScaleX(get(t));
147         }
148     }
149 
150     static class ScaleYset extends ViewOscillator {
151         @Override
setProperty(View view, float t)152         public void setProperty(View view, float t) {
153             view.setScaleY(get(t));
154         }
155     }
156 
157     static class TranslationXset extends ViewOscillator {
158         @Override
setProperty(View view, float t)159         public void setProperty(View view, float t) {
160             view.setTranslationX(get(t));
161         }
162     }
163 
164     static class TranslationYset extends ViewOscillator {
165         @Override
setProperty(View view, float t)166         public void setProperty(View view, float t) {
167             view.setTranslationY(get(t));
168         }
169     }
170 
171     static class TranslationZset extends ViewOscillator {
172         @Override
setProperty(View view, float t)173         public void setProperty(View view, float t) {
174             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
175                 view.setTranslationZ(get(t));
176             }
177         }
178     }
179 
180     static class CustomSet extends ViewOscillator {
181         float[] mValue = new float[1];
182         protected ConstraintAttribute mCustom;
183 
184         @Override
setCustom(Object custom)185         protected void setCustom(Object custom) {
186             mCustom = (ConstraintAttribute) custom;
187         }
188 
189         @Override
setProperty(View view, float t)190         public void setProperty(View view, float t) {
191             mValue[0] = get(t);
192             CustomSupport.setInterpolatedValue(mCustom, view, mValue);
193         }
194     }
195 
196     static class ProgressSet extends ViewOscillator {
197         boolean mNoMethod = false;
198 
199         @Override
setProperty(View view, float t)200         public void setProperty(View view, float t) {
201             if (view instanceof MotionLayout) {
202                 ((MotionLayout) view).setProgress(get(t));
203             } else {
204                 if (mNoMethod) {
205                     return;
206                 }
207                 Method method = null;
208                 try {
209                     method = view.getClass().getMethod("setProgress", Float.TYPE);
210                 } catch (NoSuchMethodException e) {
211                     mNoMethod = true;
212                 }
213                 if (method != null) {
214                     try {
215                         method.invoke(view, get(t));
216                     } catch (IllegalAccessException e) {
217                         Log.e(TAG, "unable to setProgress", e);
218                     } catch (InvocationTargetException e) {
219                         Log.e(TAG, "unable to setProgress", e);
220                     }
221                 }
222             }
223         }
224     }
225 
226 }
227