Android属性动画的使用(上)

前言:

安卓里面由于补间动画,只是变化的是视图的内容,但是属性的话,是没有变的,就是以前大家在使用动画的时候,如果在tagView(目标视图)上设置了监听事件,但是,当tagView在移动的时候,点击事件还在原位置,这样很不方便,后面在API3.0以后就新增了属性动画,很好的解决了以上问题,而且新增的功能还可以扩展很多的动画效果,下面就先来说说ValueAnimator的重要性

分析:

动画,简单来说就是在一段时间里面进行一系列视图的变化,也就是必须有一定的过程,在数学里面也是就时间段,而不是时间刻,(小装个逼,嘻嘻!)
一、ValueAnimator(非常重要的):
1.首先ValueAnimator继承于父类的Animator,而它的实现子类ObjectAnimator以及TimeAnimator,暂时这里先不说这两个子类
2.学习新的类,肯定要先了解其API的使用:

ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 1);
        valueAnimator.setEvaluator();//设置评估者
        valueAnimator.setRepeatCount();//设置动画重复的次数
        valueAnimator.setInterpolator();//设置动画的插值器;也就是动画如何变化,就像速度的描述加速度一样
        valueAnimator.setDuration();//动画的时间
        valueAnimator.setStartDelay();//动画在开始之前延迟多少
        valueAnimator.setRepeatMode();//动画重复的方式;RESTART:开始-结束 开始-结束;REVERSE:开始-结束-开始 
        valueAnimator.addListener();//动画的监听
        valueAnimator.addUpdateListener();//动画属性值更新的监听

二、ValueAnimator的重要使用:
1.setEvaluator()的方法:

public class IntEvaluator implements TypeEvaluator {

public Integer evaluate(float fraction, Integer startValue, Integer endValue) 
{
int startInt = startValue;
return (int)(startInt + fraction * (endValue - startInt)); 
    }
}

里面有三个参数:

  • fraction:这个值是由插值器返回的一个百分比的数值,范围0~1之间
  • startValue:起始值
  • endValue:结束值

这个评估者的类里面就是返回一个一直在叠加的值,也就是一段时间里面变化的值,如果能得到这个值,是不是很多的动画效果就迎刃而解了,因为View变化的时候,其实就是时期位置在一段时间里面不断的变化,当间隔小于肉眼所感知的峥,就认为是在动

2.addUpdateListener();这个方法就是监听动画在动的过程中的回调,那么这里面应该有我们想要的东西

valueAnimator.addUpdateListener(new
ValueAnimator.AnimatorUpdateListener() {
             @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                 Object animatedValue = animation.getAnimatedValue();//这个不正式我们上面传的
                 值吗
                //在这里面我们是不是可以设置View的透明度,平移,旋转,以及放大,其实一段时间里面这还可以变换颜色
            }
        });

3.当然颜色变换的评估者系统已经给大家定义好了:

public class ArgbEvaluator implements TypeEvaluator {
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        int startInt = (Integer) startValue;
        int startA = (startInt >> 24);
        int startR = (startInt >> 16) & 0xff;
        int startG = (startInt >> 8) & 0xff;
        int startB = startInt & 0xff;

        int endInt = (Integer) endValue;
        int endA = (endInt >> 24);
        int endR = (endInt >> 16) & 0xff;
        int endG = (endInt >> 8) & 0xff;
        int endB = endInt & 0xff;

        return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
                (int)((startR + (int)(fraction * (endR - startR))) << 16) |
                (int)((startG + (int)(fraction * (endG - startG))) << 8) |
                (int)((startB + (int)(fraction * (endB - startB))));
    }
}

大家要做变背景色的效果是不是很简单就可以实现

三、ValueAnimator的高级用法

对一个Point作用:

public class Point {  
  
    private float x;  
  
    private float y;  
  
    public Point(float x, float y) {  
        this.x = x;  
        this.y = y;  
    }  
  
    public float getX() {  
        return x;  
    }  
  
    public float getY() {  
        return y;  
    }  
  
}  

Point类非常简单,只有x和y两个变量用于记录坐标的位置,并提供了构造方法来设置坐标,以及get方法来获取坐标。接下来定义PointEvaluator,如下所示:

public class PointEvaluator implements TypeEvaluator{  
  
    @Override  
    public Object evaluate(float fraction, Object startValue, Object endValue) {  
        Point startPoint = (Point) startValue;  
        Point endPoint = (Point) endValue;  
        float x = startPoint.getX() + fraction * (endPoint.getX() - startPoint.getX());  
        float y = startPoint.getY() + fraction * (endPoint.getY() - startPoint.getY());  
        Point point = new Point(x, y);  
        return point;  
    }  
  
}  

可以看到,PointEvaluator同样实现了TypeEvaluator接口并重写了evaluate()方法。其实evaluate()方法中的逻辑还是非常简单的,先是将startValue和endValue强转成Point对象,然后同样根据fraction来计算当前动画的x和y的值,最后组装到一个新的Point对象当中并返回。
这样我们就将PointEvaluator编写完成了,接下来我们就可以非常轻松地对Point对象进行动画操作了,比如说我们有两个Point对象,现在需要将Point1通过动画平滑过度到Point2,就可以这样写:

Point point1 = new Point(0, 0);  
Point point2 = new Point(300, 300);  
ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), point1, point2);  
anim.setDuration(5000);  
anim.start(); 

代码很简单,这里我们先是new出了两个Point对象,并在构造函数中分别设置了它们的坐标点。然后调用ValueAnimator的ofObject()方法来构建ValueAnimator的实例,这里需要注意的是,ofObject()方法要求多传入一个TypeEvaluator参数,这里我们只需要传入刚才定义好的PointEvaluator的实例就可以了。
好的,这就是自定义TypeEvaluator的全部用法,掌握了这些知识之后,我们就可以来尝试一下如何通过对Point对象进行动画操作,从而实现整个自定义View的动画效果。
新建一个MyAnimView继承自View,代码如下所示:

public class MyAnimView extends View {  
  
    public static final float RADIUS = 50f;  
  
    private Point currentPoint;  
  
    private Paint mPaint;  
  
    public MyAnimView(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
        mPaint.setColor(Color.BLUE);  
    }  
  
    @Override  
    protected void onDraw(Canvas canvas) {  
        if (currentPoint == null) {  
            currentPoint = new Point(RADIUS, RADIUS);  
            drawCircle(canvas);  
            startAnimation();  
        } else {  
            drawCircle(canvas);  
        }  
    }  
  
    private void drawCircle(Canvas canvas) {  
        float x = currentPoint.getX();  
        float y = currentPoint.getY();  
        canvas.drawCircle(x, y, RADIUS, mPaint);  
    }  
  
    private void startAnimation() {  
        Point startPoint = new Point(RADIUS, RADIUS);  
        Point endPoint = new Point(getWidth() - RADIUS, getHeight() - RADIUS);  
        ValueAnimator anim = ValueAnimator.ofObject(new PointEvaluator(), startPoint, endPoint);  
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {  
            @Override  
            public void onAnimationUpdate(ValueAnimator animation) {  
                currentPoint = (Point) animation.getAnimatedValue();  
                invalidate();  
            }  
        });  
        anim.setDuration(5000);  
        anim.start();  
    }  
  
}  

基本上还是很简单的,总共也没几行代码。首先在自定义View的构造方法当中初始化了一个Paint对象作为画笔,并将画笔颜色设置为蓝色,接着在onDraw()方法当中进行绘制。这里我们绘制的逻辑是由currentPoint这个对象控制的,如果currentPoint对象不等于空,那么就调用drawCircle()方法在currentPoint的坐标位置画出一个半径为50的圆,如果currentPoint对象是空,那么就调用startAnimation()方法来启动动画。
那么我们来观察一下startAnimation()方法中的代码,其实大家应该很熟悉了,就是对Point对象进行了一个动画操作而已。这里我们定义了一个startPoint和一个endPoint,坐标分别是View的左上角和右下角,并将动画的时长设为5秒。然后有一点需要大家注意的,就是我们通过监听器对动画的过程进行了监听,每当Point值有改变的时候都会回调onAnimationUpdate()方法。在这个方法当中,我们对currentPoint对象进行了重新赋值,并调用了invalidate()方法,这样的话onDraw()方法就会重新调用,并且由于currentPoint对象的坐标已经改变了,那么绘制的位置也会改变,于是一个平移的动画效果也就实现了。
下面我们只需要在布局文件当中引入这个自定义控件:

  
  
      
  
  
Android属性动画的使用(上)_第1张图片
效果

总结:有时候大家可能对一些动画可能很没有头绪,也可能是一些属性变化没有什么头绪,希望鄙人上面所讲的会对你有更大的帮助,你只要知道了思想才可能,应对更对的可能

注意:因为属性动画是API3.0以后的属性;所以在GitHub有大神给出来兼容的属性动画:只要在AS里面依赖:

compile 'com.nineoldandroids:library:2.4.0'

你可能感兴趣的:(Android属性动画的使用(上))