由来

很多人对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
@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
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
  • * 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​