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 17package android.graphics.drawable; 18 19import com.android.ide.common.rendering.api.LayoutLog; 20import com.android.internal.view.animation.NativeInterpolatorFactoryHelper_Delegate; 21import com.android.layoutlib.bridge.Bridge; 22import com.android.layoutlib.bridge.impl.DelegateManager; 23import com.android.tools.layoutlib.annotations.LayoutlibDelegate; 24 25import android.animation.Animator; 26import android.animation.AnimatorSet; 27import android.animation.ObjectAnimator; 28import android.animation.PropertyValuesHolder; 29import android.annotation.NonNull; 30import android.annotation.Nullable; 31import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT; 32import android.graphics.drawable.VectorDrawable_Delegate.VFullPath_Delegate; 33import android.graphics.drawable.VectorDrawable_Delegate.VGroup_Delegate; 34import android.graphics.drawable.VectorDrawable_Delegate.VNativeObject; 35import android.graphics.drawable.VectorDrawable_Delegate.VPathRenderer_Delegate; 36 37import java.util.ArrayList; 38import java.util.function.Consumer; 39 40/** 41 * Delegate used to provide new implementation of a select few methods of {@link 42 * AnimatedVectorDrawable} 43 * <p> 44 * Through the layoutlib_create tool, the original methods of AnimatedVectorDrawable have been 45 * replaced by calls to methods of the same name in this delegate class. 46 */ 47@SuppressWarnings("unused") 48public class AnimatedVectorDrawable_Delegate { 49 private static DelegateManager<AnimatorSetHolder> sAnimatorSets = new 50 DelegateManager<>(AnimatorSetHolder.class); 51 private static DelegateManager<PropertySetter> sHolders = new 52 DelegateManager<>(PropertySetter.class); 53 54 55 @LayoutlibDelegate 56 /*package*/ static long nCreateAnimatorSet() { 57 return sAnimatorSets.addNewDelegate(new AnimatorSetHolder()); 58 } 59 60 @LayoutlibDelegate 61 /*package*/ static void nAddAnimator(long setPtr, long propertyValuesHolder, 62 long nativeInterpolator, long startDelay, long duration, int repeatCount) { 63 PropertySetter holder = sHolders.getDelegate(propertyValuesHolder); 64 if (holder == null || holder.getValues() == null) { 65 return; 66 } 67 68 ObjectAnimator animator = new ObjectAnimator(); 69 animator.setValues(holder.getValues()); 70 animator.setInterpolator( 71 NativeInterpolatorFactoryHelper_Delegate.getDelegate(nativeInterpolator)); 72 animator.setStartDelay(startDelay); 73 animator.setDuration(duration); 74 animator.setRepeatCount(repeatCount); 75 animator.setTarget(holder); 76 animator.setPropertyName(holder.getValues().getPropertyName()); 77 78 AnimatorSetHolder set = sAnimatorSets.getDelegate(setPtr); 79 assert set != null; 80 set.addAnimator(animator); 81 } 82 83 @LayoutlibDelegate 84 /*package*/ static long nCreateGroupPropertyHolder(long nativePtr, int propertyId, 85 float startValue, float endValue) { 86 VGroup_Delegate group = VNativeObject.getDelegate(nativePtr); 87 Consumer<Float> setter = group.getPropertySetter(propertyId); 88 89 return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue, 90 endValue)); 91 } 92 93 @LayoutlibDelegate 94 /*package*/ static long nCreatePathDataPropertyHolder(long nativePtr, long startValuePtr, 95 long endValuePtr) { 96 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED, "AnimatedVectorDrawable path " + 97 "animations are not supported.", null, null); 98 return 0; 99 } 100 101 @LayoutlibDelegate 102 /*package*/ static long nCreatePathColorPropertyHolder(long nativePtr, int propertyId, 103 int startValue, int endValue) { 104 VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr); 105 Consumer<Integer> setter = path.getIntPropertySetter(propertyId); 106 107 return sHolders.addNewDelegate(IntPropertySetter.of(setter, startValue, 108 endValue)); 109 } 110 111 @LayoutlibDelegate 112 /*package*/ static long nCreatePathPropertyHolder(long nativePtr, int propertyId, 113 float startValue, float endValue) { 114 VFullPath_Delegate path = VNativeObject.getDelegate(nativePtr); 115 Consumer<Float> setter = path.getFloatPropertySetter(propertyId); 116 117 return sHolders.addNewDelegate(FloatPropertySetter.of(setter, startValue, 118 endValue)); 119 } 120 121 @LayoutlibDelegate 122 /*package*/ static long nCreateRootAlphaPropertyHolder(long nativePtr, float startValue, 123 float endValue) { 124 VPathRenderer_Delegate renderer = VNativeObject.getDelegate(nativePtr); 125 126 return sHolders.addNewDelegate(FloatPropertySetter.of(renderer::setRootAlpha, 127 startValue, 128 endValue)); 129 } 130 131 @LayoutlibDelegate 132 /*package*/ static void nSetPropertyHolderData(long nativePtr, float[] data, int length) { 133 PropertySetter setter = sHolders.getDelegate(nativePtr); 134 assert setter != null; 135 136 setter.setValues(data); 137 } 138 139 @LayoutlibDelegate 140 /*package*/ static void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) { 141 AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr); 142 assert animatorSet != null; 143 144 animatorSet.start(); 145 } 146 147 @LayoutlibDelegate 148 /*package*/ static void nReverse(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) { 149 AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr); 150 assert animatorSet != null; 151 152 animatorSet.reverse(); 153 } 154 155 @LayoutlibDelegate 156 /*package*/ static void nEnd(long animatorSetPtr) { 157 AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr); 158 assert animatorSet != null; 159 160 animatorSet.end(); 161 } 162 163 @LayoutlibDelegate 164 /*package*/ static void nReset(long animatorSetPtr) { 165 AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr); 166 assert animatorSet != null; 167 168 animatorSet.end(); 169 animatorSet.start(); 170 } 171 172 private static class AnimatorSetHolder { 173 private ArrayList<Animator> mAnimators = new ArrayList<>(); 174 private AnimatorSet mAnimatorSet = null; 175 176 private void addAnimator(@NonNull Animator animator) { 177 mAnimators.add(animator); 178 } 179 180 private void ensureAnimatorSet() { 181 if (mAnimatorSet == null) { 182 mAnimatorSet = new AnimatorSet(); 183 mAnimatorSet.playTogether(mAnimators); 184 } 185 } 186 187 private void start() { 188 ensureAnimatorSet(); 189 190 mAnimatorSet.start(); 191 } 192 193 private void end() { 194 mAnimatorSet.end(); 195 } 196 197 private void reset() { 198 end(); 199 start(); 200 } 201 202 private void reverse() { 203 mAnimatorSet.reverse(); 204 } 205 } 206 207 /** 208 * Class that allows setting a value and holds the range of values for the given property. 209 * 210 * @param <T> the type of the property 211 */ 212 private static class PropertySetter<T> { 213 final Consumer<T> mValueSetter; 214 private PropertyValuesHolder mValues; 215 216 private PropertySetter(@NonNull Consumer<T> valueSetter) { 217 mValueSetter = valueSetter; 218 } 219 220 /** 221 * Method to set an {@link Integer} value for this property. The default implementation of 222 * this method doesn't do anything. This method is accessed via reflection by the 223 * PropertyValuesHolder. 224 */ 225 public void setIntValue(Integer value) { 226 } 227 228 /** 229 * Method to set an {@link Integer} value for this property. The default implementation of 230 * this method doesn't do anything. This method is accessed via reflection by the 231 * PropertyValuesHolder. 232 */ 233 public void setFloatValue(Float value) { 234 } 235 236 void setValues(float... values) { 237 mValues = PropertyValuesHolder.ofFloat("floatValue", values); 238 } 239 240 @Nullable 241 PropertyValuesHolder getValues() { 242 return mValues; 243 } 244 245 void setValues(int... values) { 246 mValues = PropertyValuesHolder.ofInt("intValue", values); 247 } 248 } 249 250 private static class IntPropertySetter extends PropertySetter<Integer> { 251 private IntPropertySetter(Consumer<Integer> valueSetter) { 252 super(valueSetter); 253 } 254 255 private static PropertySetter of(Consumer<Integer> valueSetter, int... values) { 256 PropertySetter setter = new IntPropertySetter(valueSetter); 257 setter.setValues(values); 258 259 return setter; 260 } 261 262 public void setIntValue(Integer value) { 263 mValueSetter.accept(value); 264 } 265 } 266 267 private static class FloatPropertySetter extends PropertySetter<Float> { 268 private FloatPropertySetter(Consumer<Float> valueSetter) { 269 super(valueSetter); 270 } 271 272 private static PropertySetter of(Consumer<Float> valueSetter, float... values) { 273 PropertySetter setter = new FloatPropertySetter(valueSetter); 274 setter.setValues(values); 275 276 return setter; 277 } 278 279 public void setFloatValue(Float value) { 280 mValueSetter.accept(value); 281 } 282 283 } 284} 285