Android:ValueAnimator的使用举例

由来

很多人对ValueAnimator不熟悉,其实ValueAnimator的功能是非常强大的。它按照设定的时间和规则,在Update方法中将value友from变化到to。说起来很简单~


动画原理

我们可以使用ValueAnimator,将其由一个值变化为另外一个值,然后根据值的变化,按照一定的规则,动态修改View的属性,比如View的位置、透明度、旋转角度、大小等,即可完成了动画的效果。Yeah,就是这么简单。

Show My Code

package net.mobctrl.moveviews;

import net.mobctrl.moveviews.valueanimator.R;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

/**
 * 
 * @author Zheng Haibo
 * @web http://www.mobctrl.net
 *
 */
@SuppressLint({ "ClickableViewAccessibility", "NewApi" })
public class MainActivity extends Activity implements OnTouchListener {

    private ImageView ivMove;
    private RelativeLayout rlRoot;
    private TextView tvTips;
    private int topTitleHeight;
    private Button animatorBtn1;
    private Button animatorBtn2;
    private Button animatorBtn3;
    private Button animatorBtn4;
    private int width;
    private int height;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ivMove = (ImageView) findViewById(R.id.iv_move);
        rlRoot = (RelativeLayout) findViewById(R.id.rl_root);
        tvTips = (TextView) findViewById(R.id.tv_tips);
        animatorBtn1 = (Button) findViewById(R.id.btn_move_animator_1);
        animatorBtn2 = (Button) findViewById(R.id.btn_move_animator_2);
        animatorBtn3 = (Button) findViewById(R.id.btn_move_animator_3);
        animatorBtn4 = (Button) findViewById(R.id.btn_move_animator_4);

        animatorBtn1.setOnClickListener(animatorClickListener);
        animatorBtn2.setOnClickListener(animatorClickListener);
        animatorBtn3.setOnClickListener(animatorClickListener);
        animatorBtn4.setOnClickListener(animatorClickListener);
        rlRoot.setOnTouchListener(this);
        tvTips.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

            }
        });

    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            int[] locations = new int[2];
            tvTips.getLocationInWindow(locations);
            topTitleHeight = locations[1];
            break;
        case MotionEvent.ACTION_MOVE:
            moveViewByLayout(ivMove, (int) event.getRawX(),
                    (int) event.getRawY());
            break;
        case MotionEvent.ACTION_UP:
            break;
        }
        return true;
    }

    /**
     * 修改view的位置
     * 
     * @param view
     * @param rawX
     * @param rawY
     */
    private void moveViewByLayout(View view, int rawX, int rawY) {
        int left = rawX - ivMove.getWidth() / 2;
        int top = rawY - topTitleHeight - ivMove.getHeight() / 2;
        int width = left + view.getWidth();
        int height = top + view.getHeight();
        view.layout(left, top, width, height);
    }

    private OnClickListener animatorClickListener = new OnClickListener() {

        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.btn_move_animator_1:
                moveLinePath();
                break;
            case R.id.btn_move_animator_2:
                moveCirclePath();
                break;
            case R.id.btn_move_animator_3:
                rotateAndAlpha();
                break;
            case R.id.btn_move_animator_4:
                scaleAnimator();
                break;
            default:
                break;
            }
        }
    };

    /**
     * 按直线轨迹运动
     */
    protected void moveLinePath() {
        width = rlRoot.getWidth();
        height = rlRoot.getHeight();
        ValueAnimator xValue = ValueAnimator.ofInt(width / 10, width / 2);
        xValue.setDuration(1000);
        xValue.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 轨迹方程 y = 1.5*x
                int x = (Integer) animation.getAnimatedValue();
                int y = (int) (1.5f * x);
                System.out.println("debug:(x,y) = " + x + "," + y);
                moveViewByLayout(ivMove, x, y);
            }
        });
        xValue.setInterpolator(new LinearInterpolator());
        xValue.start();
    }

    /**
     * 先放大后缩小
     */
    protected void scaleAnimator() {
        final float scale = 0.6f;
        AnimatorSet scaleSet = new AnimatorSet();

        ValueAnimator valueAnimatorSmall = ValueAnimator.ofFloat(1.0f, scale);
        valueAnimatorSmall.setDuration(500);

        ValueAnimator valueAnimatorLarge = ValueAnimator.ofFloat(scale, 1.0f);
        valueAnimatorLarge.setDuration(500);

        valueAnimatorSmall.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float scale = (Float) animation.getAnimatedValue();
                ivMove.setScaleX(scale);
                ivMove.setScaleY(scale);
            }
        });
        valueAnimatorLarge.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float scale = (Float) animation.getAnimatedValue();
                ivMove.setScaleX(scale);
                ivMove.setScaleY(scale);
            }
        });

        scaleSet.play(valueAnimatorLarge).after(valueAnimatorSmall);
        scaleSet.start();

    }

    /**
     * 旋转的同时进行透明度变化
     */
    protected void rotateAndAlpha() {

        ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 360);
        valueAnimator.setDuration(1000);
        valueAnimator.addUpdateListener(new AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int rotateValue = (Integer) animation.getAnimatedValue();
                ivMove.setRotation(rotateValue);
                float fractionValue = animation.getAnimatedFraction();
                ivMove.setAlpha(fractionValue);
            }
        });
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.start();
    }

    /**
     * 圆形运行
     */
    protected void moveCirclePath() {
        width = rlRoot.getWidth();
        height = rlRoot.getHeight();
        final int R = width / 4;
        ValueAnimator tValue = ValueAnimator.ofFloat(0,
                (float) (2.0f * Math.PI));
        tValue.setDuration(1000);
        tValue.addUpdateListener(new 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);
                System.out.println("debug:(x,y) = " + x + "," + y);
                moveViewByLayout(ivMove, x, y);
            }
        });
        tValue.setInterpolator(new DecelerateInterpolator());
        tValue.start();
    }
}

  • * main.xml *
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rl_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:id="@+id/tv_tips"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:text="move your finger on the screen,next activity -> click this" />

    <LinearLayout
        android:id="@+id/ll_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/tv_tips"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/btn_move_animator_1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Anim1" />

        <Button
            android:id="@+id/btn_move_animator_2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Anim2" />

        <Button
            android:id="@+id/btn_move_animator_3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Anim3" />

        <Button
            android:id="@+id/btn_move_animator_4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Anim4" />
    </LinearLayout>

    <ImageView
        android:id="@+id/iv_move"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_centerInParent="true"
        android:background="@drawable/ic_launcher"
        android:contentDescription="@null" />

</RelativeLayout>

项目链接

  • * GitHub *

https://github.com/nuptboyzhb/MoveViewValueAnimator

更多交流

Android开发联盟QQ群:272209595

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。