1.ObjectAnimatorObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", 300);
animator.setDuration(1000);
animator.start();
常用的属性动画的属性值:
translationX和translationY:这两个属性作为一种增量来控制着View对象从它布局容器的左上角坐标偏移位置
rotation、rotationX和rotationY:这三个属性控制View对象围绕支点进行2D和3D旋转
scaleX和scaleY:这两个属性控制着View对象围绕它的支点进行2D缩放
pivotX和pivotY:这两个属性控制着View对象的支点位置,围绕这个支点进行旋转和缩放变换处理。默认情况下,该支点的位置就是View对象的中心点
x和y:描述了View对象在它容器中的最终位置,它是最初的左上角坐标translationX、translationY值的累计和
alpha:它表示View对象的aplha透明度。默认值是1不透明,0代表完全透明
要操纵的属性必须具有get、set方法,不然ObjectAnimator就无法起效。可以通过自定义一个属性类或者包装类,来间接地给这个属性增加get、set方法private static class WrapperView {
private View mTarget;
public WrapperView(View target) {
this.mTarget = target;
}
public int getWidth() {
return mTarget.getLayoutParams().width;
}
public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}
通过以上代码,就给一个属性包装了一层,并给他技工了get、set方法。使用时只需要操纵包装类就可以间接调用get、set方法了,代码如下:public void btnButton(View view) {
WrapperView wrapperView = new WrapperView(view);
ObjectAnimator.ofInt(wrapperView, "width", 500).setDuration(1000).start();
}
2.PropertyValuesHolder
类似视图动画中的AnimationSet,在属性动画中,如果针对一个对象的多个属性,要同时作用多种动画,可以使用PropertyValuesHolder来实现。比如在平移的过程中,同时改变X、Y轴的缩放,可以这样实现:public void btnButton(View view) {
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationX", 300F);
PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("scaleX", 1F, 0F, 1F);
PropertyValuesHolder p3 = PropertyValuesHolder.ofFloat("scaleY", 1F, 0F, 1F);
ObjectAnimator.ofPropertyValuesHolder(view, p1, p2, p3).setDuration(1000).start();
}
在代码中,分别使用PropertyValuesHolder对象来控制translationX scaleX scaleY这三个属性,最后调用ObjectAnimator.ofPropertyValuesHolder()方法实现多属性动画的共同作用,整个实现方法非常类似AnimationSet是使用
3.ValueAnimator
ObjectAnimator继承自ValueAnimator,ValueAnimator本身不提供任何动画效果,它更像一个数值发生器,用来产生具有一定规律的数字,从而让调用者来控制动画的实现过程,ValueAnimator的一般使用方法如下:public void btnButton(View view) {
final Button button = (Button) view;
ValueAnimator animator = ValueAnimator.ofInt(0, 100);
animator.setDuration(5000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
button.setText("" + value);
}
});
animator.start();
}
通过ValueAnimator生成0~100的“渐变”数字,并将数字设置到Button上,从而使得Button显示0~100的数字,具有动画的效果
4.动画事件的监听
一个完整的动画具有start repeat end cancel四个过程,通过Android提供的接口,可以很方便监听这四个事件:public void btnButton(View view) {
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0F, 1F);
animator.setDuration(1000);
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
Toast.makeText(Main2Activity.this, "anim end", Toast.LENGTH_SHORT).show();
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.start();
}
当然,大部分时候,我们只关心onAnimationEnd事件,所以Android也提供了一个AnimatorListenerAdapter来让我们选择必要的事件进行监听,代码如下:animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
Toast.makeText(Main2Activity.this, "anim end", Toast.LENGTH_SHORT).show();
}
});
5.AnimatorSet
对于一个属性同时作用多个属性动画效果,前面已经用PropertyValuesHolder实现了这样的效果。而AnimatorSet不仅能实现这样的效果,同时也能实现更为精确的顺序控制。同样是实现上面使用PropertyValuesHolder演示的那个动画效果,如果使用AnimatorSet实现如下:public void btnButton(View view) {
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 300F);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1F, 0F, 1F);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY", 1F, 0F, 1F);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
// set.playTogether(animator1, animator2, animator3);
// set.playSequentially(animator1, animator2, animator3);
set.play(animator2).with(animator3);
set.play(animator1).after(animator3);
set.start();
}
在属性动画中,AnimatorSet正是通过playTogether()、playSequentially()、set.play().with()、before()、after()这些方法来控制多个动画的协同工作方式,从而做到对动画播放顺序的精确控制。
7.插值器Interpolator
插值器是动画中一个非常重要的概念,通过插值器Interpolator可以定义动画变换速率
下面这个例子,通过设置插值器animator.setInterpolator(new BounceInterpolator())使得每个ImageView在动画停止时有一个小球弹跳的效果
public class Main3Activity extends AppCompatActivity implements View.OnClickListener {
private int[] res = {R.id.imageView_a, R.id.imageView_b, R.id.imageView_c, R.id.imageView_d,
R.id.imageView_e, R.id.imageView_f, R.id.imageView_g, R.id.imageView_h,};
private List imageViewList = new ArrayList<>();
private boolean flag = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
for (int i = 0; i
ImageView imageView = findViewById(res[i]);
imageView.setOnClickListener(this);
imageViewList.add(imageView);
}
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.imageView_a:
if (flag) {
startAnim();
} else {
closeAnim();
}
break;
default:
Toast.makeText(this, "click" + v.getId(), Toast.LENGTH_SHORT).show();
break;
}
}
private void closeAnim() {
for (int i = 1; i
ObjectAnimator animator = ObjectAnimator.ofFloat(imageViewList.get(i),
"translationY", i * 100F, 0F);
animator.setDuration(1000);
// 设置插值器
animator.setInterpolator(new BounceInterpolator());
animator.setStartDelay(i * 100);
animator.start();
flag = true;
}
}
private void startAnim() {
for (int i = 1; i
ObjectAnimator animator = ObjectAnimator.ofFloat(imageViewList.get(i),
"translationY", 0F, i * 100F);
animator.setDuration(1000);
// 设置插值器
animator.setInterpolator(new BounceInterpolator());
animator.setStartDelay(i * 200);
animator.start();
flag = false;
}
}
}