在开发项目的过程中几乎都会使用自定义控件,无论是组合型的或者画出来的。而要想使自定义控件满足我们所希望的各种效果,就必须得掌握动画的使用,今天就来总结一下如何使用。
在Android动画中,总共有两种类型的动画
1.View Animation(视图动画): View Animation:Tween Animation(补间动画)和Frame Animation(逐帧动画);
2.Property Animator(属性动画);:ValueAnimator和ObjectAnimator
区别:
1.View动画只是实现了一种视觉上的动画效果,其本身的在屏幕上的位置等属性是不会变化的。属性动画是通过改变控件的属性来实现的一种动画效果。
2.属性动画是3.0之后出来的,它可以实现View动画实现不了的功能比如渐变色等。
一:View动画使用
1.translate:平移动画
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fillAfter="true"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="200"
android:toYDelta="200">
</translate>
Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate1);
textView1.startAnimation(animation);
代码写法:
//TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
TranslateAnimation animation1=new TranslateAnimation(0,200,0,200);
animation1.setDuration(2000);
animation1.setFillAfter(true);
animation1.setRepeatCount( 10000);
animation1.setRepeatMode(Animation.REVERSE);
textView1.startAnimation(animation1);
2.rotate:旋转动画
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0.0"
android:toDegrees="620.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="700"
android:fillAfter="true"
android:repeatCount="3"
android:repeatMode="reverse"
>
</rotate>
Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate1);
textView1.startAnimation(animation);
代码写法:
RotateAnimation animation1=new RotateAnimation(0.0f,620.0f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
animation1.setDuration(1000);
animation1.setRepeatCount(3);
animation1.setFillAfter(true);
animation1.setRepeatMode(Animation.REVERSE);
textView1.startAnimation(animation1);
3.scale:缩放动画
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0.0"
android:toXScale="1.2"
android:fromYScale="0.0"
android:toYScale="1.2"
android:pivotX="50%"
android:pivotY="50%"
android:duration="700"
android:fillBefore="true"
android:repeatCount="3"
android:repeatMode="restart"
>
</scale>
Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale1);
textView1.startAnimation(animation);
代码写法:
//ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)
//ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
ScaleAnimation animation1=new ScaleAnimation(0.0f,1.0f,0f,1.0f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
animation1.setDuration(3000);
animation1.setFillBefore(true);
animation1.setRepeatCount(3);
animation1.setRepeatMode(Animation.RESTART);
textView1.startAnimation(animation1);
alpha:透明度动画
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="2000"
android:fillBefore="true"
android:repeatCount="3"
android:repeatMode="restart"
>
</alpha>
//0.0 全透明 1.0不透明
Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha1);
textView1.startAnimation(animation);
代码写法:
// AlphaAnimation(float fromAlpha, float toAlpha)
AlphaAnimation animation1=new AlphaAnimation(0.0f,1.0f);
animation1.setDuration(3000);
animation1.setFillBefore(true);
animation1.setRepeatCount(3);
animation1.setRepeatMode(Animation.RESTART);
textView1.startAnimation(animation1);
5.set集合动画:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:fillAfter="true">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
<scale
android:fromXScale="0.0"
android:toXScale="1.2"
android:fromYScale="0.0"
android:toYScale="1.2"
android:pivotX="50%"
android:pivotY="50%"/>
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
Animation animation = AnimationUtils.loadAnimation(this, R.anim.allanimation);
textView1.startAnimation(animation);
代码写法:
AlphaAnimation alphaAnim = new AlphaAnimation(0.1f,1.0f);
ScaleAnimation scaleAnim = new ScaleAnimation(0.0f,1.2f,0.0f,1.2f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
RotateAnimation rotateAnim = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
AnimationSet setAnim=new AnimationSet(true);
setAnim.addAnimation(alphaAnim);
setAnim.addAnimation(scaleAnim);
setAnim.addAnimation(rotateAnim);
setAnim.setDuration(3000);
setAnim.setFillAfter(true);
textView1.startAnimation(setAnim);
6.差值器:
AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
AnticipateInterpolator 开始的时候向后然后向前甩
AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
BounceInterpolator 动画结束的时候弹起
CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator 在动画开始的地方快然后慢
LinearInterpolator 以常量速率改变
OvershootInterpolator 向前甩一定值后再回到原来位置
二:属性动画(ValueAnimator和ObjectAnimator)
1.核心方法:
ValueAnimator ofInt(int... values)
ValueAnimator ofFloat(float... values)
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int animatedValue = (int) animation.getAnimatedValue();
}
});
// ValueAnimator animator=ValueAnimator.ofFloat(0f,0.2f,0.4f,0.8f,1.0f);
ValueAnimator animator=ValueAnimator.ofInt(0,360);
animator.setDuration(9000);
animator.setRepeatCount(20);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int animatedValue = (int) animation.getAnimatedValue();
// textView1.setTextScaleX(animatedValue);
// textView1.setAlpha(animatedValue);
// textView1.setScaleX(animatedValue);
// textView1.setScaleX(animatedValue);
textView1.setRotation(animatedValue);
Log.e("TAG",animatedValue+"");
//刷新布局
textView1.requestLayout();
}
});
说明:在不设置差值器情况下 如果设置A->B 则是匀速的 ,如果设置多个数值,他是根据这个规律的。
这种属性动画不是直接对View进行动画操作,而是对一组数据进行操作处理,然后在addUpdateListener拿到这种值并对 View进行属性操作。
原理:首先设置动画参数ofInt,ofFloat---->获取Interceptor系数-->计算出Evaluater的值-->addUpdateListener中获取该值。最后手动操作设置属性。
2.自定义Interpolator 和自定义Evalutor
public class MyIntercepter implements Interpolator {
@Override
public float getInterpolation(float input) {
return input*3;
}
}
public class MyEvaluate implements TypeEvaluator<Integer>{
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
int start=startValue;
int end=endValue;
int cuur= (int) (start+fraction*(end=start));
return cuur;
}
}
animation1.setInterpolator(new MyIntercepter());
对于ValueAnimator中的addUpdateListener回调中获取的值animation.getAnimatedValue(); 就是cuur。 我们可以通过自定义Evaluate来修改获取的实时的值。
fraction这个系数是什么呢? 他就是MyIntercepter差值器的getInterceptor的返回值,input是0--1的值代表着时间进度情况,只与时间有关。我们根据要求计算出对应的数学函数作为返回值,这样就改变了动画的速率,或者说 改变了cuur的系数,从而达到动画效果。比如前半段时间运动快后半段时间运动慢等操作。 例如:
public class MyIntercepter1 implements Interpolator {
@Override
public float getInterpolation(float input) {
if (input<=0.5){
input= (float) (input*1.5);
}else if (input>0.5){
input= (float) (0.5+input*0.5);
}
return input*3;
}
}
public class MyEvaluate1 implements TypeEvaluator<MyPoint>{
@Override
public MyPoint evaluate(float fraction, MyPoint startValue, MyPoint endValue) {
int start=startValue.getRadio();
int end=endValue.getRadio();
int cuur= (int) (start+fraction*(end-start));
return new MyPoint(cuur);
}
}
ValueAnimator ofObject(TypeEvaluator evaluator, Object... values);
ValueAnimator animator=ValueAnimator.ofObject(new MyEvaluate1(),
new MyPoint(5),new MyPoint(20));
animator.setDuration(9000);
animator.setRepeatCount(20);
animator.setRepeatMode(ValueAnimator.RESTART);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
MyPoint animatedValue = (MyPoint) animation.getAnimatedValue();
Log.e("TAG",animatedValue+"");
//刷新布局
textView1.requestLayout();
}
});
}
颜色变化:
ValueAnimator animator = ValueAnimator.ofInt(0xffffff00,0xff0000ff);
animator.setEvaluator(new ArgbEvaluator());
animator.setDuration(3000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int curValue = (int)animation.getAnimatedValue();
tv.setBackgroundColor(curValue);
}
});
animator.start();
一般情况 不需要自义。系统提供的一般可以满足。特殊情况 还得通过数学计算得到一个函数,让动画的相关参数的返回值按照计算返回,达到想要的动画的目的。
3.ObjectAnimator 属性动画 :与上一个动画不同的是,这个属性动画是对View进行属性操作,从而达到动画效果。
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
第一个参数动画要操作的是哪个控件
第二个参数动画要操作这个控件的哪个属性
第三个参数是可变长参数,指这个属性值是从哪变到哪
原理:首先设置动画参数ofInt,ofFloat---->获取Interceptor系数-->计算出Evaluater的值,然后通过反射将值set到被操作控件的属性方法中。 根据原理可以看到想要修改某个控件的属性就必须要有该属性的setProper方法,并且要遵循驼式命名法,使用的时候是将"set"去掉,并首字母小写。例如:
public void setTranslationX(float translationX)
ObjectAnimator animator=ObjectAnimator.ofFloat(textView1,"translationX",50,200);
//1. 平移:translationX、translationY
public void setTranslationX(float translationX);
public void setTranslationY(float translationY);
//2. 缩放:scaleX、scaleY
public void setScaleX(float scaleX);
public void setScaleY(float scaleY);
//3.旋转度数:rotation、rotationX、rotationY
public void setRotation(float rotation);
public void setRotationX(float rotationX);
public void setRotationY(float rotationY);
//4.透明度:alpha
public void setAlpha(float alpha);
自动义属性:只要掌握其原理就行,只是在View里面加一些set属性的方法就行,再是用的时候和上面的一样用,就是如此简单。另外也可以设置getProperty方法,此方法是当ofInt odFloat 的属性值参数只有一个的时候,就默认把传进来的当做结束值,把getProperty的值作为起始值。
组合动画:
ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(textView1, "translationY", 0, 300, 0);
ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(textView2, "translationY", 0, 400, 0);
AnimatorSet animatorSet = new AnimatorSet();
//按顺序
animatorSet.playSequentially(tv1TranslateY,tv2TranslateY);
//同时播放
animatorSet.playTogether(tv1TranslateY,tv2TranslateY);
animatorSet.setDuration(1000);
animatorSet.start();
ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(textView1, "translationY", 0, 400, 0);
ObjectAnimator tv1Alpha = ObjectAnimator.ofFloat(textView1, "alpha", 0.1f, 1.0f);
ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(textView2, "translationY", 0, 500, 0);
ObjectAnimator tv2Alpha = ObjectAnimator.ofFloat(textView2, "alpha", 0.1f, 1.0f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(tv1TranslateY).before(tv2Alpha).with(tv2TranslateY).after(tv1Alpha);
animatorSet.setDuration(1000);
animatorSet.start();
监听方法:
animatorSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
Log.e("TAG", "animator start");
}
@Override
public void onAnimationEnd(Animator animation) {
Log.e("TAG", "animator end");
}
@Override
public void onAnimationCancel(Animator animation) {
Log.e("TAG", "animator cancel");
}
@Override
public void onAnimationRepeat(Animator animation) {
Log.e("TAG", "animator repeat");
}
});
上面的一些使用法发比较简单 基本看看代码就能理解。动画这块内容还是不少的,但是理解了 还是很好记忆的。有什么不对的 还望不吝指教啊 。