Home | History | Annotate | Download | only in drawable
      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 android.graphics.drawable;
     18 
     19 import com.android.ide.common.rendering.api.LayoutLog;
     20 import com.android.internal.view.animation.NativeInterpolatorFactoryHelper_Delegate;
     21 import com.android.layoutlib.bridge.Bridge;
     22 import com.android.layoutlib.bridge.impl.DelegateManager;
     23 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
     24 
     25 import android.animation.Animator;
     26 import android.animation.AnimatorSet;
     27 import android.animation.ObjectAnimator;
     28 import android.animation.PropertyValuesHolder;
     29 import android.annotation.NonNull;
     30 import android.annotation.Nullable;
     31 import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
     32 import android.graphics.drawable.VectorDrawable_Delegate.VFullPath_Delegate;
     33 import android.graphics.drawable.VectorDrawable_Delegate.VGroup_Delegate;
     34 import android.graphics.drawable.VectorDrawable_Delegate.VNativeObject;
     35 import android.graphics.drawable.VectorDrawable_Delegate.VPathRenderer_Delegate;
     36 
     37 import java.util.ArrayList;
     38 import 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")
     48 public 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