Android 动画之属性动画

1.简介

Animation一般动画就是我们前面学的帧动画和补间动画。Animator则是本节要讲的属性动画。



2.图解







3.属性动画之ValueAnimator详解


3.1.使用流程

3.1.1.调用ValueAnimator的ofInt(),ofFloat()或ofObject()静态方法创建ValueAnimator实例。

3.1.2.调用实例的setXxx方法设置动画持续时间,插值方式,重复次数等。

3.1.3.调用实例的addUpdateListener添加AnimatorUpdateListener监听器,在该监听器中 可以获得ValueAnimator计算出来的值,你可以值应用到指定对象上。

3.1.4.调用实例的start()方法开启动画! 另外我们可以看到ofInt和ofFloat都有个这样的参数:float/int... values代表可以多个值。


3.2.代码实现


3.2.1.布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="直线动画" />


    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="缩放动画" />


    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="旋转动画" />


    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="画圆动画" />


    <ImageView
        android:id="@+id/imageview"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_gravity="center"
        android:layout_marginTop="40dp"
        android:background="@drawable/progress_loading_image_01" />


</LinearLayout>


3.2.2.Java代码

public class AnimationDrawableActivity extends AppCompatActivity {


    private Button btn_one;
    private Button btn_two;
    private Button btn_three;
    private Button btn_four;
    private LinearLayout linearLayout;
    private ImageView imageView;
    private int width;
    private int height;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animationdrawable);
        linearLayout = (LinearLayout) findViewById(R.id.linearlayout);
        btn_one = (Button) findViewById(R.id.button1);
        btn_two = (Button) findViewById(R.id.button2);
        btn_three = (Button) findViewById(R.id.button3);
        btn_four = (Button) findViewById(R.id.button4);
        imageView = (ImageView) findViewById(R.id.imageview);


        btn_one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                lineAnimator();
            }
        });


        btn_two.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                scaleAnimator();
            }
        });


        btn_three.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                raAnimator();
            }
        });


        btn_four.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                circleAnimator();
            }
        });


    }


    /**
     * 移动图片
     * */


    private void moveView(View view, int rawX, int rawY) {
        int left = rawX - imageView.getWidth() / 2;
        int top = rawY - imageView.getHeight();
        int width = left + view.getWidth();
        int height = top + view.getHeight();
        view.layout(left, top, width, height);
    }


    //按轨迹方程来运动
    private void lineAnimator() {
        width = linearLayout.getWidth();
        height = linearLayout.getHeight();
        ValueAnimator xValue = ValueAnimator.ofInt(height, 0, height / 4, height / 2, height / 4 * 3, height);
        xValue.setDuration(3000L);
        xValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 轨迹方程 x = width / 2
                int y = (Integer) animation.getAnimatedValue();
                int x = width / 2;
                moveView(imageView, x, y);
            }
        });
        xValue.setInterpolator(new LinearInterpolator());
        xValue.start();
    }


    //缩放效果
    private void scaleAnimator() {
        ValueAnimator vValue = ValueAnimator.ofFloat(1.0f, 0.6f, 1.2f, 1.0f, 0.6f, 1.2f, 1.0f);
        vValue.setDuration(1000L);
        vValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float scale = (Float) animation.getAnimatedValue();
                imageView.setScaleX(scale);
                imageView.setScaleY(scale);
            }
        });
        vValue.setInterpolator(new LinearInterpolator());
        vValue.start();
    }




    //旋转的同时透明度变化
    private void raAnimator() {
        ValueAnimator rValue = ValueAnimator.ofInt(0, 360);
        rValue.setDuration(1000L);
        rValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int rotateValue = (Integer) animation.getAnimatedValue();
                imageView.setRotation(rotateValue);
                float fractionValue = animation.getAnimatedFraction();
                imageView.setAlpha(fractionValue);
            }
        });
        rValue.setInterpolator(new DecelerateInterpolator());
        rValue.start();
    }


    //圆形旋转
    protected void circleAnimator() {
        width = linearLayout.getWidth();
        height = linearLayout.getHeight();
        final int R = width / 4;
        ValueAnimator tValue = ValueAnimator.ofFloat(0, (float) (2.0f * Math.PI));
        tValue.setDuration(1000);
        tValue.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 圆的参数方程 x = R * sin(t) y = R * cos(t)
                float t = (Float) animation.getAnimatedValue();
                int x = (int) (R * Math.sin(t) + width / 2);
                int y = (int) (R * Math.cos(t) + height / 2);
                moveView(imageView, x, y);
            }
        });
        tValue.setInterpolator(new DecelerateInterpolator());
        tValue.start();
    }


}


使用的流程非常简单,先创建ValueAnimator对象,调用ValueAnimator.ofInt/ofFloat 获得,然后设置动画持续时间。addUpdateListener添加AnimatorUpdateListener事件监听, 然后使用参数animation的getAnimatedValue()获得当前的值,然后我们可以拿着这个值 来修改View的一些属性,从而形成所谓的动画效果,接着设置setInterpolator动画渲染模式, 最后调用start()开始动画的播放。





4.属性动画之ObjectAnimator详解


4.1.说明

比起ValueAnimator,ObjectAnimator显得更为易用,通过该类我们可以直接对任意对象的任意属性进行动画操作。而不单单只是View对象, 不断地对对象中的某个属性值进行赋值,然后根据对象属性值的改变再来决定如何展现出来。比如为TextView设置如下动画: ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f);

这里就是不断改变alpha的值,从1f - 0f,然后对象根据属性值的变化来刷新界面显示,从而 展现出淡入淡出的效果,而在TextView类中并没有alpha这个属性。

ObjectAnimator内部机制是: 寻找传输的属性名对应的get和set方法,而非找这个属性值。


4.2.代码实现


4.2.1.布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/linearlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="动画1" />


    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="动画2" />


    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="动画3" />


    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="动画4" />


    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="动画5" />


    <TextView
        android:id="@+id/textview"
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_marginTop="40dp"
        android:gravity="center"
        android:layout_gravity="center"
        android:text="使用ObjectAnimator设置View相关动画!"/>




</LinearLayout>


4.2.2.Java代码

public class AnimationDrawableActivity extends AppCompatActivity {


    private Button btn_one;
    private Button btn_two;
    private Button btn_three;
    private Button btn_four;
    private Button btn_five;
    private LinearLayout linearLayout;
    private int height;
    private ObjectAnimator animator1;
    private ObjectAnimator animator2;
    private ObjectAnimator animator3;
    private ObjectAnimator animator4;
    private AnimatorSet animSet;
    private TextView textView;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animationdrawable);
        linearLayout = (LinearLayout) findViewById(R.id.linearlayout);
        textView= (TextView) findViewById(R.id.textview);
        btn_one = (Button) findViewById(R.id.button1);
        btn_two = (Button) findViewById(R.id.button2);
        btn_three = (Button) findViewById(R.id.button3);
        btn_four = (Button) findViewById(R.id.button4);
        btn_five= (Button) findViewById(R.id.button5);
        height = linearLayout.getHeight();
        initAnimator();


        btn_one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                animator1.setDuration(3000l);
                animator1.start();
            }
        });


        btn_two.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                animator2.setDuration(3000l);
                animator2.start();
            }
        });


        btn_three.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                animator3.setDuration(3000l);
                animator3.start();
            }
        });


        btn_four.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                animator4.setDuration(3000l);
                animator4.start();
            }
        });


        btn_five.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //将前面的动画集合到一起
                animSet = new AnimatorSet();
                animSet.play(animator4).with(animator3).with(animator2).after(animator1);
                animSet.setDuration(5000l);
                animSet.start();
            }
        });


    }


    //初始化动画
    private void initAnimator() {
        animator1 = ObjectAnimator.ofFloat(textView, "alpha", 1f, 0f, 1f, 0f, 1f);
        animator2 = ObjectAnimator.ofFloat(textView, "rotation", 0f, 360f, 0f);
        animator3 = ObjectAnimator.ofFloat(textView, "scaleX", 2f, 4f, 1f, 0.5f, 1f);
        animator4 = ObjectAnimator.ofFloat(textView, "translationY", height / 8, -100, height / 2);
    }


}





5.属性动画之Evaluator详解


5.1.图解



5.2.IntEvaluator的源码




5.3.代码实现


5.3.1.Java Bean类

public class Point {


    private float x;
    private float y;


    public Point() {
    }


    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }


    public float getX() {
        return x;
    }


    public float getY() {
        return y;
    }


    public void setX(float x) {
        this.x = x;
    }


    public void setY(float y) {
        this.y = y;
    }

}



5.3.2.TypeEvaluator实现类

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

}



5.3.3.自定义View

public class AnimView extends View {


    public static final float RADIUS = 80.0f;
    private Point currentPoint;
    private Paint mPaint;


    public AnimView(Context context) {
        this(context, null);
    }


    public AnimView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }


    public AnimView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    private void init() {
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.BLUE);
    }


    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(3000l);
        anim.start();
    }


    @Override
    protected void onDraw(Canvas canvas) {
        if (currentPoint == null) {
            currentPoint = new Point(RADIUS, RADIUS);
            drawCircle(canvas);
            startAnimation();
        } else {
            drawCircle(canvas);
        }
    }

}



5.3.4.Java代码使用

setContentView(new AnimView(this));





6.Interpolator(补间器)详解


6.1.图解




6.2.Interpolator的内部实现机制







附1:帧动画讲解:Android 动画之帧动画

附2:补间动画讲解:Android 动画之补间动画

猜你喜欢

转载自blog.csdn.net/weixin_37730482/article/details/80609979
今日推荐