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