ObjectAnimation动画属性

ObjectAnimator,通过设置改变对象的属性来实现动画效果,常用的方法有这么几种,ofFloat()、ofInt()、ofObject()、ofArgb()、ofPropertyValuesHolder(),具体含义及使用我们在下面的实例中进行讲解。

一、动画类型

使用ObjectAnimator也是可以轻松的实现平移、缩放、旋转、透明度这几种动画效果的,与补间动画的使用效果是一样的,那就先来看看这几种常用的动画是怎么实现的。

工程代码里就是一个ImageView控件和Activity,

?
1
2
3
4
5
6
<!--?xml version= "1.0" encoding= "utf-8" ?-->
<relativelayout android:layout_height= "match_parent" android:layout_width= "match_parent" xmlns:android= "http://schemas.android.com/apk/res/android" >
 
<imageview android:id= "@+id/head" android:layout_centerinparent= "true" android:layout_height= "wrap_content" android:layout_width= "wrap_content" android:src= "@drawable/head" >
 
</imageview></relativelayout>
?
1
2
3
4
5
6
@Override
protected void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_object_animator);  
         head = (ImageView) findViewById(R.id.head);
     }

我们这里就是对ImageView控件head实现动画效果,本质就是改变head的属性。

1.平移(translate)

?
1
// 平移 private void translateAnimation() { ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX", 0.0f, 350.0f, 0.0f); objectAnimator.setDuration(2000); objectAnimator.setRepeatCount(Animation.INFINITE); objectAnimator.setRepeatMode(Animation.RESTART); objectAnimator.start(); }
 

target:动画操作的对象,我们这里的操作对象就是ImageView控件head

 

propertyName:属性名称,这里的"translationX"属性值意思就是在水平方向移动,如果是"translationY"就是在垂直方向移动,下面讲到的其动画效果也是这个意思,这个属性值跟我们在xml文件中设置属性值得名称是一致的,比如

?
1
"android:translationY"

values:动画过渡值,过渡值可以有一个到N个,如果是一个值的话,就默认是这个动画过渡值的结束值,如果有N个值,动画就在这N个值之间过渡,如本例中有三个过渡值"0.0f, 350.0f, 0f",意思就是从当前位置向右滑到350的位置,再滑到位置0,即初始位置。

然后是动画的设置,

?
1
2
3
objectAnimator.setDuration( 2000 ); //动画的时间间隔
objectAnimator.setRepeatCount(Animation.INFINITE); //重复次数
objectAnimator.setRepeatMode(Animation.RESTART); //重复模式

最后start,动画就开始执行了

?
1
objectAnimator.start();

2.缩放(scale)

?
1
2
3
4
5
6
7
8
// 缩放
private void scaleXAnimation() {
     ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "scaleX" , 1 .0f, 1 .5f);
     objectAnimator.setDuration( 2000 );
     objectAnimator.setRepeatCount(Animation.INFINITE);
     objectAnimator.setRepeatMode(Animation.RESTART);
     objectAnimator.start();
}

?
1
<strong> 3 .旋转(rotate)</strong>
?
1
2
3
4
5
6
7
8
// 旋转
private void rotateAnimation() {
     ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "rotationX" , 0 .0f, 90 .0f, 0 .0F);
     objectAnimator.setDuration( 2000 );
     objectAnimator.setRepeatCount(Animation.INFINITE);
     objectAnimator.setRepeatMode(Animation.RESTART);
     objectAnimator.start();
}

?
1
<strong> 4 .透明度(alpha)</strong>
?
1
2
3
4
5
6
7
8
// 透明度
private void alphaAnimation() {
     ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "alpha" , 1 .0f, 0 .3f, 1 .0F);
     objectAnimator.setDuration( 2000 );
     objectAnimator.setRepeatCount(Animation.INFINITE);
     objectAnimator.setRepeatMode(Animation.RESTART);
     objectAnimator.start();
}

 

可能我们也注意到了,在缩放效果的实例中,图片被放大后就保持当前的状态,没有变为初始的样子,这是因为我们在设置过渡值是最终的状态是1.5f,就放大到1.5倍,并没有让它回到原来的状态,从这点就可以看出,属性动画是真真切切的可以改变控件的属性的,这是与补间动画的最大不同,补间动画在动画结束后都将回到初始状态。所以说,属性动画的使用就显得更加的灵活。至于上面的其他三个实例,最终回到初始状态,是因为我们在设过渡值的时候最终状态设定的就是初始状态。

刚才我们讨论了几种常见的动画效果,如果仅有这些功能的话,那就与补间动画没有太大的区别。其实,属性动画还可以设置其他的属性值。ObjectAnimator的ofObject方法,就是用来对任意对象进行动画设置的,如字体颜色,直接看实例

 

?
1
<textview android:id= "@+id/txt" android:layout_centerinparent= "true" android:layout_height= "wrap_content" android:layout_width= "wrap_content" android:text= "测试颜色变化" android:textcolor= "@android:color/black" android:textsize= "32sp" ></textview>
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int startColor = 0xffff0000 ;
int endColor = 0xff00ff00 ;
ObjectAnimator objectAnimator4 = ObjectAnimator.ofObject(txt, "textColor" , new TypeEvaluator() {
@Override
public Object evaluate( float fraction, Object startValue, Object endValue) {
int startInt = (Integer) startValue;
int startA = (startInt >> 24 ) & 0xff ;
int startR = (startInt >> 16 ) & 0xff ;
int startG = (startInt >> 8 ) & 0xff ;
int startB = startInt & 0xff ;
 
int endInt = (Integer) endValue;
int endA = (endInt >> 24 ) & 0xff ;
int endR = (endInt >> 16 ) & 0xff ;
int endG = (endInt >> 8 ) & 0xff ;
int endB = endInt & 0xff ;
 
return ( int )((startA + ( int )(fraction * (endA - startA))) << 24 ) |
                 ( int )((startR + ( int )(fraction * (endR - startR))) << 16 ) |
                 ( int )((startG + ( int )(fraction * (endG - startG))) << 8 ) |
                 ( int )((startB + ( int )(fraction * (endB - startB))));
     }
}, startColor, endColor);
objectAnimator4.setDuration( 3000 );
objectAnimator4.start();

 

ofObject方法的原型

?
1
public static ObjectAnimator ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values)
我们看到它比ofFloat多了一个TypeEvaluator参数,它是用来告知系统如何进行属性值过渡的,由于ofObject是任意属性,所以需要自己实现TypeEvaluator,ofFloat没有该参数是因为系统默认实现了其过渡行为FloatEvaluator,关于TypeEvaluator我们会单独讲解,这边就不在详述了。
除了字体颜色外,还可以设置背景色"backgroundColor"等。
刚才的字体颜色除了使用ofObject方法外,还可以使用ofArgb,但需要SDK版本21上支持,目前市面上很多机型还是21以下的,暂时我们最好不要使用。
?
1
2
ObjectAnimator objectAnimator2 = ObjectAnimator.ofArgb(txt, "textColor" , 0x000 , 0x00FF00 );
objectAnimator2.start();

二、常用设置
在上面的例子中,我们已经对动画进行了一些设置,如间隔、重复次数等等,下面就将常见的设置罗列出来。

1.setInterpolator():设置动画插值

控制动画的变化速率,系统中定义了好几种Interpolator:

LinearInterpolator--均匀的速率改变

AccelerateDecelerateInterpolator--先加速后减速

AccelerateInterpolator--加速

DecelerateInterpolator--减速

CycleInterpolator--动画循环播放特定的次数,速率改变沿着正弦曲线
2.setDuration():设置动画执行时间,动画时间以毫秒为单位(ms)

3.setRepeatCount():设置动画重复次数

大于0的值就代表重复几次,如果需要无限循环,设为-1,上面的Animation.INFINITE是系统给的常量,值为-1,代表无限循环,我们建议使用这个常量,如果设为0呢?也是执行一次。

4.setRepeatMode():设置动画重复模式

5.setStartDelay():设置动画延时操作,也是以毫秒为单位(ms)

6.setTarget():设置动画的对象

操作对象,上面的例子中将动画对象通过ofXXX方传递,如果需要改变动画对象,但动画效果不变,我们可以使用该方法来设置。

?
1
objectAnimator.setTarget(txt); //将动画对象head变为txt
7.setEvaluator():设置动画过度的评估者,即设置TypeEvaluator对象,后面会详细介绍
 
三、组合动画
上面讲到的都是单一的动画,在实际使用时,有可能同时需要多种动画效果,比如同时在水平方向和垂直方向进行缩放并且同时绕水平方向旋转,要实现这样的效果就必须用到组合动画。可以有三种方式来实现,一一讲解。
1.AnimatorSet
AnimatorSet可以让几个动画同时执行,也可以设置执行顺序、延迟执行等,
?
1
2
3
4
after(Animator anim)--将现有动画插入到传入的动画之后执行
after( long delay)--将现有动画延迟指定毫秒后执行
before(Animator anim)--将现有动画插入到传入的动画之前执行
with(Animator anim)--将现有动画和传入的动画同时执行
?
1
 
?
1
playSequentially(Animator... items)--依次执行
?
1
2
3
4
5
6
7
8
9
private void multiAnimation() {
         ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(head, "scaleX" , 1 .0f, 2 .5f, 1 .0f);
         ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(head, "scaleY" , 1 .0f, 2 .5f, 1 .0f);
         ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(head, "rotationX" , 0 .0f, 90 .0f, 0 .0F);
         AnimatorSet animatorSet = new AnimatorSet();
         animatorSet.play(objectAnimator1).with(objectAnimator2).with(objectAnimator3);
         animatorSet.setDuration( 2000 );
         animatorSet.start();
     }

 

让动画同时执行除了使用with方法外,还可以用playTogether方法,

 

?
1
animatorSet.playTogether(objectAnimator1, objectAnimator2, objectAnimator3);
其他几种就不在演示了。
2.PropertyValuesHolder
?
1
这种方式只能多个动画一起执行,不同设置先后顺序。
?
1
2
3
4
5
6
7
8
private void multiAnimation2() {
         PropertyValuesHolder valuesHolder = PropertyValuesHolder.ofFloat( "scaleX" , 1 .0f, 2 .5f, 1 .0f);
         PropertyValuesHolder valuesHolder1 = PropertyValuesHolder.ofFloat( "scaleY" , 1 .0f, 2 .5f, 1 .0f);
         PropertyValuesHolder valuesHolder2 = PropertyValuesHolder.ofFloat( "rotationX" , 0 .0f, 90 .0f, 0 .0F);
         ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(head, valuesHolder, valuesHolder1, valuesHolder2);
         objectAnimator.setDuration( 2000 );
         objectAnimator.start();
}
3.ViewPropertyAnimator
该类是多属性动画,从名字就可以看出该类的作用对象是view,当一个view对象需要同时执行多个属性动画的时候就可以考虑使用该类了。比如说:一个ImageView先右移动的同时进行放大一倍的动画效果实现如下
?
1
2
3
4
5
6
7
8
private void viewPropertyAnimator() {
         ViewPropertyAnimator animator = head.animate();
         animator.translationX( 200 )
                 .scaleX( 2 )
                 .scaleY( 2 )
                 .setDuration( 2000 )
                 .start();
     }

四、动画的监听

一般情况下,我们除了需要动画效果外,还需要对动画的执行过程进行监听,在执行前、执行结束后或者执行过程中,做出相应的处理,比如动画结束后,请求网络数据。系统给我们提供几种监听接口,来监听动画的各个状态,如AnimatorListener,

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private void animationListener() {
         ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX" , 0 .0f, 350 .0f, 0f);
         objectAnimator.setDuration( 2000 );
         objectAnimator.addListener( new Animator.AnimatorListener() {
             @Override
             public void onAnimationStart(Animator animation) {
                 Log.d( "dingfeng" , "onAnimationStart......" );
             }
 
             @Override
             public void onAnimationEnd(Animator animation) {
                 Log.d( "dingfeng" , "onAnimationEnd......" );
             }
 
             @Override
             public void onAnimationCancel(Animator animation) {
                 Log.d( "dingfeng" , "onAnimationCancel......" );
             }
 
             @Override
             public void onAnimationRepeat(Animator animation) {
                 Log.d( "dingfeng" , "onAnimationRepeat......" );
             }
         });
         objectAnimator.start();
     }

可以根据不同需求来实现接口里面的四个方法,可以根据需要做相应的处理。但有时候你会觉得我不需要监听动画的四种状态,我只需要监听动画结束时候的状态,使用上面的方法就会感觉代码臃肿了,不过没关系,Android系统给我们提供了一个更好用的方法,

?
1
2
3
4
5
6
7
8
9
10
11
12
private void animationListener2() {
         ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX" , 0 .0f, 350 .0f, 0f);
         objectAnimator.setDuration( 2000 );
         objectAnimator.addListener( new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
                 super .onAnimationEnd(animation);
                 Log.d( "dingfeng" , "onAnimationEnd......" );
             }
         });
         objectAnimator.start();
     }
?
1
2
3
可以看出,我们使用了AnimatorListenerAdapter动画接口适配器代替AnimatorListener接口。其实AnimatorListenerAdapter的源码只是一个实现了AnimatorListener接口的抽象类而已,
你需要监听哪种动画状态就重写哪种方法就可以了。
除此之外,AnimatorUpdateListener接口就可以读取到动画的每个更新值。
?
1
 
?
1
private void animationListener3() { ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(head, "translationX" , 0 .0f, 350 .0f, 0f); objectAnimator.setDuration( 2000 ); objectAnimator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = ( float )animation.getAnimatedValue(); Log.d( "dingfeng" , "onAnimationUpdate......" +value); } }); objectAnimator.start(); }
一般情况下不太用到这个接口,但是在自定义动画的时候,通过该接口,可以实现很多复杂的效果。
五、xml编写动画
当然,我们也可以在xml文件中配置动画,这样做可以比较好的复用这些动画,减少代码量。
1.在资源目录下创建animator文件夹
将编写的xml文件放在该目录下,如下图 

我们创建两个动画文件,一个是旋转动画,一个组合动画

 

?
1
2
<!--?xml version= "1.0" encoding= "utf-8" ?-->
<objectanimator android:duration= "'2000'" android:propertyname= "'rotationX'" android:repeatcount= "-1" android:repeatmode= "restart" android:valuefrom= "'0'" android:valueto= "'180'" android:valuetype= "'floatType'" xmlns:android= "'http://schemas.android.com/apk/res/android'" ></objectanimator>
?
1
2
3
4
5
6
7
8
9
<!--?xml version= "1.0" encoding= "utf-8" ?-->
<set android:duration= "'2000'" android:ordering= "'sequentially'" xmlns:android= "'http://schemas.android.com/apk/res/android'" ><!--动画执行顺序 sequentially:顺序执行;together:同时执行。 -->
<objectanimator android:propertyname= "'translationX'" android:valuefrom= "'0'" android:valueto= "'200'" android:valuetype= "'floatType'" >
 
     <set android:ordering= "'together'" >
         <objectanimator android:propertyname= "'scaleX'" android:valuefrom= "'1'" android:valueto= "'2'" android:valuetype= "'floatType'" >
         <objectanimator android:propertyname= "'scaleY'" android:valuefrom= "'1'" android:valueto= "'2'" android:valuetype= "'floatType'" >
     </objectanimator></objectanimator></set>
</objectanimator></set>
2.加载动画
使用AnimatorInflater加载动画文件
?
1
2
3
4
head = (ImageView) findViewById(R.id.head);
Animator animator = AnimatorInflater.loadAnimator( this , R.animator.multi);
animator.setTarget(head);
animator.start();
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您好,关于使用DoTween制作动画的问题,下面是一个简单的示例: 假设您想要在Unity中创建一个上下摆动的动画,您可以使用DoTween的DOTween.Sequence()方法来创建一个有序的动画序列,并使用DOTween.LoopType.Yoyo选项来使其循环播放。 具体步骤如下: 1. 首先,确保您已经安装了DOTween插件。您可以从Unity Asset Store中下载并导入它。 2. 创建一个新的GameObject并将其命名为“Object”。 3. 在Object上添加一个新的RectTransform组件,并将其位置设置为(0, 0, 0)。 4. 在Object上添加一个新的Image组件,并将其颜色设置为白色。 5. 在Object上添加一个新的脚本,并将其命名为“ObjectAnimation”。 6. 在ObjectAnimation脚本中,导入DOTween命名空间: using DG.Tweening; 7. 在ObjectAnimation脚本中,创建一个新的方法来处理动画序列的创建和播放: private void Animate() { // 创建动画序列 Sequence sequence = DOTween.Sequence(); // 设置动画序列的循环方式为Yoyo sequence.SetLoops(-1, LoopType.Yoyo); // 添加上升动画 sequence.Append(transform.DOMoveY(100f, 1f).SetEase(Ease.OutQuad)); // 添加下降动画 sequence.Append(transform.DOMoveY(0f, 1f).SetEase(Ease.InQuad)); // 播放动画 sequence.Play(); } 8. 在ObjectAnimation脚本的Start()方法中调用Animate()方法: private void Start() { Animate(); } 9. 在Unity编辑器中运行场景,您应该可以看到Object上下摆动的动画效果。 希望这个示例能够对您有所帮助,如有疑问请随时询问!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值