Android 自定义动画view(小变大,旋转,色值)

也不知道到看了多少的动画总结了,但是用到的时候太少,过段时间就会忘记了。

既然如此,我选择直接去动手学习,步步进阶。

效果:

上代码之前我们分析一下才会加深自己的印象:

  • 需要画一个矩形 和 一个圆形
  • 需要计算位置,距离,大小
  • 需要缩放,旋转,颜色渐变动画

代码:

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:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.administrator.firsttest.activity.AnimActivity">

    <com.example.administrator.firsttest.animView.MyView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/myView"
        />

</LinearLayout>

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:均匀速度。

猜你喜欢

转载自blog.csdn.net/lhk147852369/article/details/81485252