也不知道到看了多少的动画总结了,但是用到的时候太少,过段时间就会忘记了。
既然如此,我选择直接去动手学习,步步进阶。
效果:
上代码之前我们分析一下才会加深自己的印象:
代码:
package com.example.administrator.firsttest.animView;
import android.animation.AnimatorSet;
import android.animation.Keyframe;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.LinearInterpolator;
import android.widget.TextView;
/**
* Created by Administrator on 2018/8/7.
*/
public class MyView extends View {
Paint mPaint;
int lineWidth = 10;
int ratio = 50;
int mColor = Color.BLUE;
float rotate;
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mColor);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(lineWidth);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 由于动画中有更改颜色,所以这里每次onDraw都要重新设置下画笔颜色
mPaint.setColor(mColor);
//旋转动画,直接旋转画布即可
canvas.rotate(rotate, getWidth() / 2, getHeight() / 2);
// 画正方形,ratio为可边长的一半
canvas.drawRect(getWidth() / 2 - ratio / 2, getHeight() / 2 - ratio / 2, getWidth() / 2 + ratio / 2, getHeight() / 2 + ratio / 2, mPaint);
// 画圆形,ratio为半径
canvas.drawCircle(getWidth() / 2, getHeight() / 2 - 2 * ratio, ratio, mPaint);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void start(){
// 旋转动画,通过改变rotate值实现
ValueAnimator rotateAni = ValueAnimator.ofFloat(0, 360);
//无限重复
rotateAni.setRepeatCount(Animation.INFINITE);
// 设置监听,赋值给rotate
rotateAni.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
rotate = (float) animation.getAnimatedValue();
invalidate();
}
});
//放大动画,通过改变ratio实现
ValueAnimator rotateAnimator = ValueAnimator.ofInt(50, 100);
rotateAnimator.setInterpolator(new LinearInterpolator());
rotateAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
ratio = (int) animation.getAnimatedValue();
}
});
rotateAnimator.setRepeatCount(-1);
// 设置重复的模式为原样恢复,即放大后再按原路缩小,这样才不会出现跳动
rotateAnimator.setRepeatMode(ValueAnimator.REVERSE);
//颜色变化动画
ValueAnimator colorAni = ValueAnimator.ofArgb(Color.BLUE, Color.GREEN);
colorAni.setInterpolator(new LinearInterpolator());
colorAni.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mColor = (int) animation.getAnimatedValue();
}
});
colorAni.setRepeatCount(-1);
// 设置重复的模式为原样恢复,即放大后再按原路缩小,这样才不会出现跳动
colorAni.setRepeatMode(ValueAnimator.REVERSE);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.play(rotateAnimator).with(colorAni).with(rotateAni);
set.start();
Keyframe keyframe = Keyframe.ofFloat(0f, 0);
}
}
//我在例子中用的都是ValueAnimator,其实还有其它相关类,比如ObjectAnimator改变透明度:
//ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
//animator.setDuration(5000);
//animator.start();
//另外还有ViewPropertyAnimator,用起来更方便,不过只有有限的方法,比如让view在x轴y轴都平衡500:
//textview.animate().x(500).y(500).setDuration(5000)
//.setInterpolator(new BounceInterpolator());
//最后最后,再说一个PropertyValuesHolder,它保存了动画过程中所需要操作的属性和对应的值,
//通常和Keyframe一起使用。像实现一个View抖动动画时,你用上面的需要写很多重复的动画进行串联起来,
//但用Keyframe就可以很好的一次性把动画描述清楚。Keyframe其实就是动画的关键帧。举个抖动的实现例子:
//Keyframe frame0 = Keyframe.ofFloat(0f, 0);
// Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
// Keyframe frame2 = Keyframe.ofFloat(1, 0);
// PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2);
// Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder);
//animator.setDuration(1000);
// animator.start();
xml:
activity:
package com.example.administrator.firsttest.activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.example.administrator.firsttest.R;
import com.example.administrator.firsttest.animView.MyView;
public class AnimActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_anim);
((MyView) findViewById(R.id.myView)).start();
}
}
代码中已经有注释了,但是我们还是要去总结一下
动画中的三种动画:
1.补间动画
通过场景里的对象不断做图像变换(平移,缩放,旋转,透明度)从而产生动画效果,是一种渐近式动画,并支持自定义。
2.属性动画
属相动画通过动态地改变对象的属性从而达到动画效果。
3.帧动画
帧动画其实也属于View
动画。通过顺序播放一系列图像从而产生动画效果,可以简单理解为图片切换动画效果,但图片过多过大会导致OOM
动画中的插值器
@android:anim/accelerate_interpolator: 越来越快
@android:anim/decelerate_interpolator:越来越慢
@android:anim/accelerate_decelerate_interpolator:先快后慢
@android:anim/anticipate_interpolator: 先后退一小步然后向前加速
@android:anim/overshoot_interpolator:快速到达终点超出一小步然后回到终点
@android:anim/anticipate_overshoot_interpolator:到达终点超出一小步然后回到终点
@android:anim/bounce_interpolator:到达终点产生弹球效果,弹几下回到终点
@android:anim/linear_interpolator:均匀速度。