一、背景
有了补间动画,为什么还需要属性动画
补间动画限制:
1、补间动画只能定义两个关键帧在透明、旋转、位移和倾斜这四个属性的变换,但是属性动画可以定义任何属性的变化。
3、补间动画只能对 UI 组件(view)执行动画,但属性动画可以对任何对象执行动画。
4、补间动画没有改变view 的属性,只是加了视觉效果
5、补间动画效果单一
属性动画的优势:
1、任何对象都可以,不在限制于View
2、不止是四种基本变换
二、属性动画
1、常用的类
图片.pngValueAnimator:
特定时间内执行一个动画,动画执行类,核心
ObjectAnimator:
一个对象的一个属性动画,动画执行类
AnimatorSet:
动画集合
TimeAnimator:
时序监听回调工具
TimeInterpolator:
时间差值(插值器接口),控制动画变化率
TypeEvaluator:
类型估值(估值器接口),设置属性计算方式,根据属性的始末值和插值一起计算当前时间的属性值
AnimatorInflate:
加载属性动画的xml文件
LayoutTransition:
布局动画
ViewPropetyValuesHolder
为view的动画提供一种更为便捷的用法
PerpertyValuesHolder
保存动画过程中所需操作的属性和对应的值
KeyFrame:
控制每个时间段执行的动画距离
AnimationListener:动画事件监听
AnimationUpdateListener:动画事件监听
AnimatorListenerAdapter:动画事件监听
其中:
插值器:根据时间流逝的百分比计算出当前属性值改变的百分比
LinearInterpolator(线性插值器):匀速动画。
AccelerateDecelerateInterpolator(加速减速插值器):动画两头慢,中间快。
DecelerateInterpolator(减速插值器):动画越来越慢。
估值器:根据当前属性改变的百分比来计算改变后的属性值。
IntEvaluator:针对整型属性
FloatEvaluator:针对浮点型属性
ArgbEvaluator:针对Color属性
引用:https://www.cnblogs.com/huolongluo/p/6523552.html
2、ValueAnimator
属性动画最核心的类
控制 值 的变化,之后 手动 赋值给对象的属性,从而实现动画
ValueAnimator.ofInt(int... values) -- 整型数值
ValueAnimator.ofFloat(float... values) -- 浮点型数值
ValueAnimator.ofObject(TypeEvaluator evaluator, Object... values) -- 自定义对象类型
private void animatorDemo() {
ValueAnimator valueAnimator = ValueAnimator.ofInt(30, 500);
valueAnimator.setDuration(3000);
valueAnimator.setInterpolator(new DecelerateInterpolator());
// valueAnimator.setInterpolator(new CycleInterpolator(3));
// valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
valueAnimator.setRepeatMode(ValueAnimator.RESTART);
valueAnimator.setRepeatCount(2);
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
Log.i("Simon", "onAnimationStart");
}
@Override
public void onAnimationEnd(Animator animation) {
Log.i("Simon", "onAnimationEnd");
}
@Override
public void onAnimationCancel(Animator animation) {
Log.i("Simon", "onAnimationCancel");
}
@Override
public void onAnimationRepeat(Animator animation) {
Log.i("Simon", "onAnimationRepeat");
}
});
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int v = (int)animation.getAnimatedValue();
Log.i("Simon", "onAnimationUpdate v: " + v);
// LinearLayout.LayoutParams param = (LinearLayout.LayoutParams)mImageView.getLayoutParams();
// param.leftMargin = v;
// mImageView.setLayoutParams(param);
mImageView.setPadding(v, 0, 0, 0);
}
});
valueAnimator.start();
}
3、ObjectAnimator
属性 作用 数值类型
alpha 透明度 float
translationX X方向的位移 float
translationY Y方向的位移 float
scaleX X方向的缩放倍数 float
scaleY Y方向的缩放倍数 float
rotation 以屏幕方向为轴的旋转度数 float
rotationX 以X轴为轴的旋转度数 float
rotationY 以Y轴为轴的旋转度数 float
1、xml方式:
res/animator/alpha.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:repeatCount="1"
android:repeatMode="reverse"
android:propertyName="alpha"
android:valueFrom="0"
android:valueTo="1"
android:interpolator="@android:anim/accelerate_interpolator"
android:valueType="floatType" />
res/animator/ratation.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:repeatCount="1"
android:repeatMode="reverse"
android:propertyName="rotation"
android:valueFrom="100"
android:valueTo="190"
android:interpolator="@android:anim/accelerate_interpolator"
android:valueType="floatType" />
将xml形式的animator读入代码中执行
private void xmlObjectAnimatorDemo() {
// ObjectAnimator objectAnimator = (ObjectAnimator)AnimatorInflater.loadAnimator(this, R.animator.alpha);
ObjectAnimator objectAnimator = (ObjectAnimator)AnimatorInflater.loadAnimator(this, R.animator.roration);
objectAnimator.setTarget(mImageView);
objectAnimator.start();
}
2、纯java代码实现
private void objectAnimatorDemo() {
// ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "alpha", 0, 1);
// ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "translationX", 0, 200);
// ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "translationY", 0, 200, 100);
// ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "scaleX", 1, 5);
// ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "scaleY", 1, 5);
// ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "rotation", 0, 270);
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "rotationY", 0, 180, -100);
objectAnimator.setDuration(3000);
objectAnimator.setInterpolator(new AccelerateInterpolator());
// objectAnimator.setInterpolator(new DecelerateInterpolator());
// objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
// objectAnimator.setInterpolator(new CycleInterpolator(3));
// objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
// objectAnimator.setRepeatMode(ValueAnimator.RESTART);
// objectAnimator.setRepeatCount(2);
objectAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationCancel(Animator animation) {
Log.i("Simon", "AnimatorListenerAdapter onAnimationCancel");
}
@Override
public void onAnimationEnd(Animator animation) {
Log.i("Simon", "AnimatorListenerAdapter onAnimationEnd");
}
@Override
public void onAnimationRepeat(Animator animation) {
Log.i("Simon", "AnimatorListenerAdapter onAnimationRepeat");
}
@Override
public void onAnimationStart(Animator animation) {
Log.i("Simon", "AnimatorListenerAdapter onAnimationStart");
}
@Override
public void onAnimationPause(Animator animation) {
Log.i("Simon", "AnimatorListenerAdapter onAnimationPause");
}
@Override
public void onAnimationResume(Animator animation) {
Log.i("Simon", "AnimatorListenerAdapter onAnimationResume");
}
});
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.i("Simon", "addUpdateListener onAnimationUpdate value:" + animation.getAnimatedValue());
}
});
objectAnimator.start();
}
4、AnimationSet
AnimatorSet.play(Animator anim) :播放当前动画
AnimatorSet.after(long delay) :将现有动画延迟x毫秒后执行
AnimatorSet.with(Animator anim) :将现有动画和传入的动画同时执行
AnimatorSet.after(Animator anim) :将现有动画插入到传入的动画之后执行
AnimatorSet.before(Animator anim) : 将现有动画插入到传入的动画之前执行
AnimatorSet.playSequentially(Animator... items):参数中的动画列表依次执行
AnimatorSet.playTogether(Animator... items):参数中的动画同时执行
private void animatorSetDemo() {
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(3000);
animatorSet.setInterpolator(new LinearInterpolator());
ObjectAnimator translationX = ObjectAnimator.ofFloat(mImageView, "translationX", 0, 300);
ObjectAnimator rotation = ObjectAnimator.ofFloat(mImageView, "rotation", 0, 720);
ObjectAnimator scaleX = ObjectAnimator.ofFloat(mImageView, "scaleX", 1, 5);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(mImageView, "scaleY", 1, 5);
ObjectAnimator alpha = ObjectAnimator.ofFloat(mImageView, "alpha", 1, 0);
animatorSet.playSequentially(translationX, rotation, scaleX, scaleY, alpha);
// animatorSet.playTogether(scaleX, scaleY);
// animatorSet.play(translationX).before(rotation);
// animatorSet.play(scaleX).with(scaleY).after(3000).before(alpha);
animatorSet.start();
}
补充: SVG动画
Google在Android5.X中增加了对SVG矢量图形的支持,这对于创造新的高效率动画具有很深远的意义。
1、svg
A.可伸缩矢量图形(Scalable Vector Graphics)
B.定义用于网络的基于矢量的图形
C.使用XML格式定义图形
D.图像在放大或改变尺寸的情况下其图形质量不会有所损失
E.万维网联盟的标准
F.与诸如DOM和XML之类的W3C标准是一个整体
2、path标签
A. M = moveto(x, y):将画笔移动到指定的坐标位置上,但是并没有发生绘制。
B. L = lineto(x, y):画一条直线到指定的坐标位置上。
C. H = horizontal lineto(x):画水平线在指定的x坐标位置。
D. V = vertical lineto(y):画一条垂直线在指定的y坐标位置。
E. C = curveto(x1, y1, x2, y2, endX, endY):三次贝赛曲线
F. S = smooth curveto(x2, y2, endX, endY):三次贝赛曲线
G. G = quadratic Belzier curveto(x, y, endX, endY):二次贝赛曲线
H. T = smooth quadratic Belizer curveto(endX, endY):映射前面路径后的终点
I. A = elliptical Arc(rx, ry, xRotation, flag1, flag2, x, y):弧线
J. Z = colsepath():关闭路径
注意:
A. 坐标轴是以(0,0)为中心的, x轴水平向右,y轴水平向下。
B. 所有指令大小写均可。大写表示绝对坐标,参照全局坐标系;小写表示相对坐标,参照父容器的坐标系。
C. 指令和数据间的空格可以省略。
D. 同一个指令可以使用多次。
3、例子
drawable/vector.xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="110"
android:viewportHeight="110">
<group
android:name="test"
android:pivotX="55"
android:pivotY="55">
<path
android:pathData="M 26,50
a 25,25,0,0,0,25,25"
android:strokeWidth="2"
android:strokeColor="@android:color/holo_blue_bright" />
</group>
</vector>
animator/anim.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="5000"
android:interpolator="@android:anim/overshoot_interpolator"
android:propertyName="rotation"
android:repeatCount="3"
android:startOffset="-1"
android:valueFrom="0"
android:valueTo="360" />
</set>
drawable/animated_vector.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vector">
<target
android:name="test"
android:animation="@animator/anim" />
</animated-vector>
layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context=".MainActivity">
<ImageView
android:id="@+id/image_view"
android:layout_width="300dp"
android:layout_height="300dp"
android:src="@drawable/animated_vector" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button"
android:text="button" />
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(v -> {
ImageView imageView = findViewById(R.id.image_view);
AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable)imageView.getDrawable();
animationDrawable.start();
});
}
}
网友评论