欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-22 21:59:58
...

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

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

效果:

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

 

 

相关标签: 动画 自定义