之前介绍了帧动画和补间动画,这里继续介绍另外一种动画——属性动画。
属性动画是通过不断地控制控件的属性变化达到动画的效果。
一、属性动画与补间动画的区别
1、 补间动画只能作用于View上,如TextView、ImageView等,但是不能作用于View之外的对象上(如颜色、字体大小等)。而补间动画可以对颜色值做动画,实现更复杂的动画效果。
2、补间动画只能实现视角效果,并不能改变View的属性值。
二、属性动画的用法介绍
属性动画主要由 ObjectAnimator 类与 ValueAnimator类来实现的。
1、ValueAnimator:是对值做动画,先算出要变化的属性值,在通过监听值变化的函数修改对象的属性。
2、ObjectAnimator:是对一个对象做动画,绑定一个对象之后,会自动计算对象的属性,修改属性值。
本篇用到的类如下:
android.animation.ValueAnimator
ValueAnimator 类用于完成属性动画的计时、值的计算,但它不会对要添加动画的对象和属性应用这些值。因此必须监听由 ValueAnimator 计算的值的更新情况,并使用您自己的逻辑修改要添加动画的对象。
android.animation.ObjectAnimator
ObjectAnimator是最常用的属性动画,他能直接作用在对象上实现动画。
PropertyValuesHolder
ValueAnimator的常用方法如下:
方法 | 描述 |
---|---|
static ValueAnimator ofInt(int... values) | 整型渐变 |
static ValueAnimator ofArgb(int... values) | 颜色渐变 |
static ValueAnimator ofFloat(float... values) | 浮点型渐变 |
static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) | Object型渐变 |
static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) | 承载多个属性,在一个动画中改变多个属性值 |
ObjectAnimator继承于ValueAnimator,常用方法与ValueAnimator基本相同,只是参数不同,具体如下:
方法 | 描述 |
---|---|
static ValueAnimator ofInt(Object target, String propertyName, int... values) | 整型渐变 |
static ValueAnimator ofFloat(Object target, String propertyName, float... values) | 浮点型渐变 |
static ValueAnimator ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values) | Object型渐变 |
static ValueAnimator ofPropertyValuesHolder(Object target, PropertyValuesHolder... values) | 承载多个属性,在一个动画中改变多个属性值 |
其中propertyName包括如下:
alpha(透明度动画)
scaleX/scaleY(缩放动画)
translationX/translationY(平移动画)
rotation(旋转动画)
ObjectAnimator继承于ValueAnimator,而ValueAnimator继承于Animator,因此有如下共通的方法。
方法 | 描述 |
---|---|
void setIntValues(int... values) | 用于设置 ofFloat 所对应的动画值列表 |
void setFloatValues(float... values) | 设置 ofFloat 所对应的动画值列表 |
void setObjectValues(Object... values) | 设置 ofObject 所对应的动画值列表 |
void setRepeatMode(int value) | 设置重复模式 |
void addUpdateListener(AnimatorUpdateListener listener) | 设置属性更新监听 |
void setInterpolator(TimeInterpolator value) | 设置差值器 |
void start() | 开始 |
void cencel() | 取消 |
void resume() | 重新开始 |
void pause() | 暂停 |
理论的就介绍到这里了,先搞个Domo。
xml文件如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:ignore="MissingConstraints"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="这是一个不正经的进度条"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.449"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.062" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="410dp"
android:layout_height="23dp"
tools:ignore="MissingConstraints"
tools:layout_editor_absoluteX="0dp"
tools:layout_editor_absoluteY="3dp" />
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="快看我,我要消失了"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.414" />
</androidx.constraintlayout.widget.ConstraintLayout>
Activity代码如下:
package com.example.animatordomo;
import androidx.appcompat.app.AppCompatActivity;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.util.Log;
import android.view.animation.BounceInterpolator;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.tv);
ProgressBar progressBar = findViewById(R.id.progressBar);
ValueAnimator valueAnimator = ValueAnimator.ofInt(0,100); //改变int的值
valueAnimator.setDuration(2000);
valueAnimator.setInterpolator(new BounceInterpolator()); //设置插值器(弹跳)
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int value = (int) valueAnimator.getAnimatedValue();
Log.i("MainActivity", "value="+value);
progressBar.setProgress(value); //取得改变的int值,然后设置进度条的进度
}
});
valueAnimator.start();
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(textView,"alpha",1f,0f); //设置透明度
objectAnimator.setDuration(4000);
objectAnimator.start();
}
}
ValueAnimator部分定义为xml文件同样可以实现功能,首先在res目录创建名为animator的目录,然后在目录创建.xml文件,类型填写animator,代码如下:
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:valueFrom="0"
android:valueTo="100"
android:startOffset="0"
android:repeatCount="0"
android:repeatMode="reverse"
android:valueType="intType"
android:interpolator="@android:anim/bounce_interpolator">
</animator>
XML各个字段含义如下:
字段 | 含义 |
---|---|
android:duration | 每次动画播放的时长 |
android:valueFrom | 初始动化值;取值范围为float,int和color,如果取值为float对应的值样式应该为89.0,取值为Int时,对应的值样式为:89;当取值为clolor时,对应的值样式为 #333333; |
android:valueTo | 动画结束值;取值范围同样是float,int和color这三种类型的值; |
android:startOffset | 动画激活延时;对应代码中的startDelay(long delay)函数; |
android:repeatCount | 动画重复次数 |
android:repeatMode | 动画重复模式,取值为repeat和reverse;repeat表示正序重播,reverse表示倒序重播 |
android:valueType | 表示参数值类型,取值为intType和floatType;与android:valueFrom、android:valueTo相对应。如果这里的取值为intType,那么android:valueFrom、android:valueTo的值也就要对应的是int类型的数值。如果这里的数值是floatType,那么android:valueFrom、android:valueTo的值也要对应的设置为float类型的值。非常注意的是,如果android:valueFrom、android:valueTo的值设置为color类型的值,那么不需要设置这个参数; |
android:interpolator | 设置加速器 |
然后在JAVA代码中使用AnimatorInflater.loadAnimator方法load这个animaor就可以了。
ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(
this,R.animator.value_animator);
JAVA方式
XML+JAVA方式