属性动画:PropertyValuesHolder

QuibblerQuibbler 2020-09-16 约 19 分钟 1893 次阅读

属性动画:PropertyValuesHolder

前面属性动画学习的过程中,在ValueAnimator中提到过ValueAnimator.ofPropertyValuesHolder(PropertyValuesHolder... values)构造方法(详见《属性动画:ValueAnimator及其监听器》3.1节),还有ObjectAnimator中也提到过ObjectAnimator.ofPropertyValuesHolder (Object target, PropertyValuesHolder... values)方法获取ObjectAnimator属性动画(详见《属性动画:ObjectAnimator基础》3.1节)。

1、PropertyValuesHolder 类

该类自API level 11添加到包android.animation中,通常用来构造属性动画,此外还有Keyframe关键帧类。 

PropertyValuesHolder包含有关属性以及在动画过程中该属性应采用的值的信息。PropertyValuesHolder对象可用于通过ValueAnimator或ObjectAnimator创建动画,这些动画可以并行操作多个不同的属性。其实那两个属性动画内部实现也是通过将传入的参数封装成PropertyValuesHolder来保存动画状态,动画的操作也是通过PropertyValuesHolder进行。

2、方法介绍

介绍PropertyValuesHolder类的常用方法。

2.1、构造方法

通过哪些方法可以获取PropertyValuesHolder实例呢?

①ofFloat(String propertyName, float... values):构造并返回具有给定属性和一组浮点值的PropertyValuesHolder

②ofFloat(Property<?, Float> property, float... values)

③ofInt(String propertyName, int... values):构造并返回具有给定属性名称和一组int值的PropertyValuesHolder

④ofInt(Property<?, Integer> property, int... values)

⑥ofKeyframe(String propertyName, Keyframe... values):构造并返回具有指定属性名称和一组值的PropertyValuesHolder对象。这些值可以是任何类型,但是类型应该一致,以便TypeEvaluator可以找到与通用类型匹配的适当值。至少两个关键帧(起始帧、结束帧)

⑦ofKeyframe(Property property, Keyframe... values)

⑧ofMultiFloat(String propertyName, float[][] values):构造并返回具有给定属性名称和一组float[]值的PropertyValuesHolder。float[]必须至少提供两个值,一个开始值和一个结束值。

⑨ofMultiFloat(String propertyName, Path path)

⑩ofMultiFloat(String propertyName, TypeConverter<V, float[]> converter, TypeEvaluator<V> evaluator, V... values)

⑪ofMultiFloat(String propertyName, TypeConverter<T, float[]> converter, TypeEvaluator<T> evaluator, Keyframe... values)

⑫ofMultiInt(String propertyName, int[][] values):构造并返回具有给定属性名称和一组int[]值的PropertyValuesHolder 。int[]必须至少提供两个值,一个开始值和一个结束值。

⑬ofMultiInt(String propertyName, Path path):构造并返回具有给定属性名称的PropertyValuesHolder,以用作多整数设置器。这些值沿路径设置动画,设置器的第一个参数设置为x坐标,第二个参数设置为y坐标。

⑭ofMultiInt(String propertyName, TypeConverter<V, int[]> converter, TypeEvaluator<V> evaluator, V... values)

⑮ofMultiInt(String propertyName, TypeConverter<T, int[]> converter, TypeEvaluator<T> evaluator, Keyframe... values)

⑯ofObject(String propertyName, TypeEvaluator evaluator, Object... values):构造并返回具有给定属性名称和一组Object值的PropertyValuesHolder。由于系统无法在未知类型的对象之间自动插值,因此需要TypeEvaluator。

⑰ofObject(String propertyName, TypeConverter<PointF, ?> converter, Path path)

⑱ofObject(Property property, TypeEvaluator<V> evaluator, V... values)

⑲ofObject(Property<?, V> property, TypeConverter<T, V> converter, TypeEvaluator<T> evaluator, T... values)

⑳ofObject(Property<?, V> property, TypeConverter<PointF, V> converter, Path path)

㉑clone():创建并返回PropertyValuesHolder对象的副本

2.2、getter和setter方法

①getPropertyName():获取动画的属性名称

②setPropertyName(String propertyName):设置动画的属性名称

③setConverter(TypeConverter converter):设置TypeConverter转换器以从值类型转换为设置器的参数类型

④setEvaluator(TypeEvaluator evaluator):TypeEvaluator将根据提供给PropertyValuesHolder的值的类型自动确定。只有float和int类型的值才可以正确插值,所有其他类型都需要设置TypeEvaluator。

⑤setFloatValues(float... values):设置ofFloat()对应动画值列表

⑥setIntValues(int... values):用于设置ofInt()所对应的动画值列表

⑦setKeyframes(Keyframe... values):用于设置ofKeyFrame()所对应的动画值列表

⑧setObjectValues(Object... values):用于设置ofObject()所对应的动画值列表

3、结合属性动画使用

PropertyValuesHolder通常用来构造ObjectAnimator属性动画,因为ObjectAnimator属性动画的构造方法有ObjectAnimator.ofPropertyValuesHolder (Object target, PropertyValuesHolder... values),第二个参数是可变长参数,说明可以传入多个PropertyValuesHolder实例,从而通过一个ObjectAnimator属性动画实现多个维度的动画一起播放。

3.1、使用ofFloat

①ofFloat构造两个PropertyValuesHolder,一个是X轴方向的缩放,效果看起来像是围绕Y轴转动。另一个是透明度属性的PropertyValuesHolder。

PropertyValuesHolder scaleXValuesHolder = PropertyValuesHolder.ofFloat("scaleX", 0f, 1.0f);
    PropertyValuesHolder alphaValuesHolder = PropertyValuesHolder.ofFloat("alpha", 0f, 1.0f);

②使用PropertyValuesHolder构造属性动画,传入多个PropertyValuesHolder

ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mImageView, scaleXValuesHolder, alphaValuesHolder);

③得到的ObjectAnimator属性动画后面操作和之前的属性动画无异,详见《属性动画:ObjectAnimator基础》

objectAnimator.setDuration(1000);
    objectAnimator.start();

3.2、使用ofInt

当尝试想要用ofInt来构造PropertyValuesHolder的时候发现,无论属性传入什么似乎都不行,可能是因为View中setter参数为int的很少。


这倒不难,可以继承View添加以int作为参数的setter方法,内部调用已有的方法即可完成转换。

public class QuibblerImageView extends AppCompatImageView {
        ...
        public void setTranslateX(int x){
            setTranslationX(x);
        }
        public void setTranslateY(int y){
            setTranslationY(y);
        }
    }

再使用PropertyValuesHolder的ofInt方法构造实例,设置自定义的TranslateX和TranslateY属性

PropertyValuesHolder translateXValuesHolder = PropertyValuesHolder.ofInt("TranslateX", 100, 200);
    PropertyValuesHolder translateYValuesHolder = PropertyValuesHolder.ofInt("TranslateY", 100, 200);
    ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mImageView, translateXValuesHolder, translateYValuesHolder);
    objectAnimator.setDuration(1000);
    objectAnimator.start();

3.3、使用ofObject

①使用ofObject创建PropertyValuesHolder必须要提供自定义的TypeEvaluator,否则内部无法计算值。

PropertyValuesHolder charValuesHolder = PropertyValuesHolder.ofObject("character", new CharacterEvaluator(), 'a', 'z');
    PropertyValuesHolder rotateYValueHolder = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
    PropertyValuesHolder textColorValue = PropertyValuesHolder.ofObject("textColor",
                                                                         new ArgbEvaluator(),
                                                                         Color.parseColor("#1d953f"),
                                                                         Color.parseColor("#1b315e"));

②创建的自定义CharacterEvaluator实现TypeEvaluator接口。关于TypeEvaluator详见《属性动画:TypeEvaluator》。

class CharacterEvaluator implements TypeEvaluator<Character> {
        @Override
        public Character evaluate(float fraction, Character startValue, Character endValue) {
            int begin = (int) startValue;
            int end = (int) endValue;
            int current = (int) (end - (end - begin) * fraction);
            return (char) current;
        }
    }

③至于TextView虽然有setText()方法,但是没有设置Character的setter方法,可以继承TextView添加自定义的setter方法

public class QuibblerTextView extends androidx.appcompat.widget.AppCompatTextView {
        public QuibblerTextView(Context context) {
            super(context);
        }
        public QuibblerTextView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
        }
        public QuibblerTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
        
        public void setCharacter(Character character) {
            setText(String.valueOf(character));
        }
    }

④使用上面构造完成的3个PropertyValuesHolder创建ObjectAnimator属性动画

ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mTextView, 
                                                                          charValuesHolder, rotateYValueHolder, textColorValue);
    objectAnimator.setDuration(2500);
    objectAnimator.start();

⑤于是一个属性动画即可完成下面需要三种动画才能实现的“复杂”旋转、内容变换、颜色动画。

相关资料:

         Docs > Reference > PropertyValuesHolder">Android Developers > Docs > Reference > PropertyValuesHolder

        Android属性动画学习与整理

Color详解

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w