Android开发Android知识移动开发

浅析Android动画(二)——Property Anim属性动

2016-08-19  本文已影响223人  JC_Hou

属性动画从字面上看就是对于属性的变换,它与变换动画最大的区别就是属性动画注重与用户的交互
举个例子:在变换动画中,将一个imageView设置点击事件,将其从左往右移动100dp,点击现有位置的imageView,并不会有点击事件,点击原有的位置将触发点击事件;而属性变化中,imageView的真实位置跟随着动画的移动而移动
变换动画请走链接浅析Android动画(一)——Tween Anim

相似的,属性动画拥有和变换动画相同的一些动画,alpha,translate,rotate,scale……但却比变化动画又更加精细,归根结底它变换的是属性,所有View对象拥有的属性都可以被操作。

属性动画也可以在布局文件中声明和在代码中声明,但从我个人角度来看,更喜欢在代码使用的形式,在这里只贴代码,有兴趣的可以自己去研究一下xml中的使用。

基本使用:

ObjectAnimator.ofFloat(Object 0,String propertyName,float...values);
ObjectAnimator.ofInt(Object 0,String propertyName,int...values);

/**

Translate

属性:"translationX","translationY","X","Y",区别在于前二者是相对对象自身的左上角,后二者是相对于屏幕的左上角

//从现有位置移动到相对于 屏幕 左上角的位置,不可以重复,因为终点位置相同,多次触发不会重复效果,横坐标与原始位置一致
ObjectAnimator.ofFloat(mImageView,"Y",100f).setDuration(1000).start();```

//从相对于 屏幕 左上角的指定位置移动到相对于 屏幕 左上角的另一个位置,可以重复触发效果,因为有起点终点,横坐标与现有原始一致
ObjectAnimator.ofFloat(mImageView,"Y",0f,100f).setDuration(1000).start();```

//从相对于 自身 左上角的指定位置移动到相对于 自身 左上角的另一个位置,可以重复触发效果,因为有起点终点,横坐标与原始位置一致
ObjectAnimator.ofFloat(mImageView,"translationY",0f,100f).setDuration(1000).start();```

//从现有位置移动到相对于 自身 左上角的坐标,多次触发不会重复效果,横坐标与原始位置一致
ObjectAnimator.ofFloat(mImageView,"translationY",100f).setDuration(1000).start();```
类似的还有X方向的变化

Rotate

属性:"rotation","rotationX","rotationY"
"rotation"与变换动画中的一致,可以声明起止点,终点大的顺时针,否则逆时针,只声明一个终点,则旋转到相对于最原始的旋转角度
"rotationX"和"rotationY"是3维的动画效果:"rotationX"表示绕与X轴同方向的中线旋转(上下翻转),"rotationY"表示绕与Y轴同方向的中线旋转(左右翻转)

//旋转到相对于原始角度的值,不可以重复 
ObjectAnimator.ofFloat(mImageView,"rotation",360f).setDuration(1000).start();```

//可以重复
ObjectAnimator.ofFloat(mImageView,"rotation",0f,180f).setDuration(1000).start();```

//绕x轴方向的中线旋转
ObjectAnimator.ofFloat(mImageView,"rotationX",0f,180f).setDuration(1000).start(); ```

//绕y轴方向的中线旋转
ObjectAnimator.ofFloat(mImageView,"rotationY",0f,360f).setDuration(1000).start();```

Scale

属性:"scaleX","scaleY"

ObjectAnimator.ofFloat(mImageView,"scaleX",0f).setDuration(1000).start();//不可多次触发
ObjectAnimator.ofFloat(mImageView,"scaleX",1f,0f).setDuration(1000).start();```
这个很好理解

#####Alpha
> 属性:"alpha"

`ObjectAnimator.ofFloat(mImageView,"alpha",0f).setDuration(1000).start();//不可多次触发`
`ObjectAnimator.ofFloat(mImageView,"alpha",1f,0f).setDuration(1000).start();`
这个也很好理解

###组合动画:
- 最简单的 :
这两个方法就已经可以进行同时进行组合动画了

ObjectAnimator.ofFloat(mImageView,"scaleX",0f).setDuration(1000).start();
ObjectAnimator.ofFloat(mImageView,"scaleY",0f).setDuration(1000).start();```

PropertyValuesHolder p1=PropertyValuesHolder.ofFloat("scaleX",1f,0f);
PropertyValuesHolder p2=PropertyValuesHolder.ofFloat("scaleY",1f,0f);`
随后再调用
ObjectAnimator.ofPropertyValuesHolder(Object o,PropertyValuesHolder...values)方法
这个方法第一个参数是操作对象,第二个参数就是PropertyValuesHolder数组了;
`objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mImageView, p1, p2);
objectAnimator.setDuration(1000);
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.setRepeatCount(-1);
objectAnimator.start();```

- 更更更好的办法:
类似于变换动画的AnimationSet动画集合,属性动画有它专门的集合:AnimatorSet,并且可以更加丰富的操作动画

先创建3个Animator:

ObjectAnimator animator1 = ObjectAnimator.ofFloat(mImageView, "alpha", 1f, 0.2f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(mImageView, "rotationX", 0f, 360f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(mImageView, "rotationY", 0f, 360f);再创建AnimatorSetA:AnimatorSet set=new AnimatorSet();```

接下来神奇的事情将会发生:

set.playTogether(animator1,animator2,animator3);//同时进行动画
set.playSequentially(animator2,animator1,animator3);//按顺序播放
set.play(animator1).with(animator2);//两个动画一起进行
set.play(animator3).after(1000);//延迟1秒
set.play(animator3).after(animator1);//3在前2个动画之后
set.play(animator3).before(animator1);//3在前2个动画之前

发现只要非常简单的代码就可以实现很丰富的动画操作

监听事件

animator和animatorSet都有此监听事件

set.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {
    }
    @Override
    public void onAnimationEnd(Animator animation) {
        Toast.makeText(AnimActivity.this,"anim end",Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onAnimationCancel(Animator animation) {
    }
    @Override
    public void onAnimationRepeat(Animator animation) {
    }
});```

这个AnimatorListener()是系统已经设置好的,但是有一点不好,四个方法都要实现,而且缺少了暂停和恢复的监听
幸好系统有另一个方法

set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
super.onAnimationCancel(animation);
}
@Override
public void onAnimationEnd(Animator animation) {
Toast.makeText(AnimActivity.this,"anim end",Toast.LENGTH_SHORT).show();
}
@Override
public void onAnimationPause(Animator animation) {
Toast.makeText(AnimActivity.this,"anim pause",Toast.LENGTH_SHORT).show();
}
@Override
public void onAnimationResume(Animator animation) {
Log.d("jc","resume");
Toast.makeText(AnimActivity.this,"anim resume",Toast.LENGTH_SHORT).show();
}
});```
在这个匿名内部类里面可以选择性的重写这六个方法。

ValueAnimator:

ObjectAnimator也是继承了ValueAnimator这个类
属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。

ValueAnimator mAnimator;
mAnimator=ValueAnimator.ofFloat(1,2);
//设置监听
mAnimator.setDuration(1000);mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float translate= (float) animation.getAnimatedValue();
        Log.d("jc”,"translate"+translate);
    }
});
//无限循环
mAnimator.setRepeatCount(-1);
mAnimator.setRepeatMode(ValueAnimator.REVERSE);
mAnimator.start();```

D/jc: translate1.0
D/jc: translate1.0007129
D/jc: translate1.0026846
D/jc: translate1.0061558
...
D/jc: translate1.9709702
D/jc: translate1.9792609
D/jc: translate1.986185
D/jc: translate1.9917226
D/jc: translate1.995858
D/jc: translate1.9984586
D/jc: translate1.9998422
D/jc: translate1.9998002
D/jc: translate1.998333
D/jc: translate1.9954448
D/jc: translate1.9914355
D/jc: translate1.9858159
D/jc: translate1.9788108
D/jc: translate1.9704404
...
D/jc: translate1.0328355
D/jc: translate1.0239887
D/jc: translate1.0169019
D/jc: translate1.0107095
D/jc: translate1.0059125
D/jc: translate1.0025245
D/jc: translate1.000555
D/jc: translate1.0000099```

可以看到结果在不断变换

上一篇下一篇

猜你喜欢

热点阅读