Android Property Animation 属性动画
属性动画 (Property Animation) 是通过不断的修改值来实现的,而初始值和结束值间的过渡动画就是由 ValueAnimator
来负责计算
ValueAnimator
动画采用一种时间循环的机制来计算值与值之间的动画过度,我们只要设定初始值和结束值,并设定动画运行时长就可以了,它会自动帮我们完成从初始值平滑过度到结束值这样的效果
除了上面说的外,ValueAnimator
还负责管理动画的次数,播放模式,以及对动画设置监听器等
属性动画相关的类
Animator
创建属性动画的基类,一般不会直接用,用它的两个子类
ValueAnimator
属性动画的管理类,会自动补间初始值与结束值之间的过渡效果
ObjectAnimator
`ValueAnimator` 的子类,允许我们对指定对象的属性执行动画
AnimatorSet
`Animator` 的子类,用于组合多个 `Animator`,并指定多个 `Animator` 是按照顺序播放还是同时播放
Evaluator (计算器)
该类用于告诉动画系统如何从初始值过度到结束值
ValueAnimator 的使用流程
-
调用
ValueAnimator
的静态方法ofInt()
,ofFloat()
或ofObject()
静态方法创建ValueAnimator
实例 -
调用实例的
setXxx
方法设置动画持续时间,插值方式,重复次数等 -
调用实例的
addUpdateListener()
添加AnimatorUpdateListener
监听器,在该监听器中 可以获得ValueAnimator
计算出来的值 -
调用实例的
start()
方法开启动画
ofInt()
、ofFloat()
、ofObject()
可以传入多个相同的参数
范例
我们写一个 demo 使用 ValueAnimator
来实现四种补间动画的效果
-
创建一个 空的 Android 项目
cn.twle.android.ValueAnimator
-
修改
activity_main.xml
布局<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ly_root" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <Button android:id="@+id/btn_one" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="动画1" /> <Button android:id="@+id/btn_two" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="动画2" /> <Button android:id="@+id/btn_three" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="动画3" /> <Button android:id="@+id/btn_four" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="动画4" /> <TextView android:id="@+id/ms_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="简单教程,简单编程" /> </LinearLayout>
-
修改
MainActivity.java
定义了四个动画,分别是:直线移动,缩放,旋转加透明,以及圆形旋转
package cn.twle.android.valueanimator; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.view.animation.DecelerateInterpolator; import android.view.animation.LinearInterpolator; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button btn_one; private Button btn_two; private Button btn_three; private Button btn_four; private LinearLayout ly_root; private TextView ms_text; private int width; private int height; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bindViews(); } private void bindViews() { ly_root = (LinearLayout) findViewById(R.id.ly_root); btn_one = (Button) findViewById(R.id.btn_one); btn_two = (Button) findViewById(R.id.btn_two); btn_three = (Button) findViewById(R.id.btn_three); btn_four = (Button) findViewById(R.id.btn_four); ms_text = (TextView) findViewById(R.id.ms_text); btn_one.setOnClickListener(this); btn_two.setOnClickListener(this); btn_three.setOnClickListener(this); btn_four.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_one: lineAnimator(); break; case R.id.btn_two: scaleAnimator(); break; case R.id.btn_three: raAnimator(); break; case R.id.btn_four: circleAnimator(); break; } } //定义一个修改ImageView位置的方法 private void moveView(View view, int rawX, int rawY) { int left = rawX - ms_text.getWidth() / 2; int top = rawY - ms_text.getHeight(); int width = left + view.getWidth(); int height = top + view.getHeight(); view.layout(left, top, width, height); } //定义属性动画的方法: //按轨迹方程来运动 private void lineAnimator() { width = ly_root.getWidth(); height = ly_root.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(ms_text, x, y); } }); xValue.setInterpolator(new LinearInterpolator()); xValue.start(); } //缩放效果 private void scaleAnimator(){ //这里故意用两个是想让大家体会下组合动画怎么用而已~ final float scale = 0.5f; 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 ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float scale = (Float) animation.getAnimatedValue(); ms_text.setScaleX(scale); ms_text.setScaleY(scale); } }); valueAnimatorLarge.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float scale = (Float) animation.getAnimatedValue(); ms_text.setScaleX(scale); ms_text.setScaleY(scale); } }); scaleSet.play(valueAnimatorLarge).after(valueAnimatorSmall); scaleSet.start(); //其实可以一个就搞定的 // 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(); // ms_text.setScaleX(scale); // ms_text.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(); ms_text.setRotation(rotateValue); float fractionValue = animation.getAnimatedFraction(); ms_text.setAlpha(fractionValue); } }); rValue.setInterpolator(new DecelerateInterpolator()); rValue.start(); } //圆形旋转 protected void circleAnimator() { width = ly_root.getWidth(); height = ly_root.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(ms_text, x, y); } }); tValue.setInterpolator(new DecelerateInterpolator()); tValue.start(); } }