属性动画的意义
一、背景
有了补间动画,为什么还需要属性动画
补间动画限制:
1、补间动画只能定义两个关键帧在透明、旋转、位移和倾斜这四个属性的变换,但是属性动画可以定义任何属性的变化。
3、补间动画只能对 UI 组件(view)执行动画,但属性动画可以对任何对象执行动画。
4、补间动画没有改变view 的属性,只是加了视觉效果
5、补间动画效果单一
属性动画的优势:
1、任何对象都可以,不在限制于View
2、不止是四种基本变换
属性动画特点
https://www.jianshu.com/p/2412d00a0ce4
ValueAnimator
java代码方式实现
package com.fenghongzhang.anim;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import androidx.appcompat.app.AppCompatActivity;
public class Main2Activity extends AppCompatActivity {
private static final String TAG = "Main2Activity";
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
initView();
}
public void btn(View view) {
ValueAnimator valueAnimator = ValueAnimator.ofInt(btn.getLayoutParams().width, 500);
//动画时间
valueAnimator.setDuration(2000);
//重复次数
valueAnimator.setRepeatCount(3);
//重复方向,
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//改变的值
Integer animatedValue = (Integer) animation.getAnimatedValue();
Log.i(TAG, "onAnimationUpdate: "+animatedValue);
btn.getLayoutParams().width = animatedValue;
btn.requestLayout();
}
});
valueAnimator.start();
}
private void initView() {
btn = (Button) findViewById(R.id.btn);
}
}
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="translationX"
android:valueFrom="100"
android:valueTo="400"
android:interpolator="@android:anim/accelerate_interpolator"
android:valueType="floatType" />
<!--android:valueFrom="0" // 初始值
android:valueTo="100" // 结束值
android:valueType="intType" // 变化值类型 :floatType & intType
//重要
android:propertyName="rotation" alpha scaleX或者scaleY translationX 变化的方式. 透明,旋转.移动
android:duration="3000" // 动画持续时间(ms),必须设置,动画才有效果
android:startOffset ="1000" // 动画延迟开始时间(ms)
android:fillBefore = “true” // 动画播放完后,视图是否会停留在动画开始的状态,默认为true
android:fillAfter = “false” // 动画播放完后,视图是否会停留在动画结束的状态,优先于fillBefore值,默认为false
android:fillEnabled= “true” // 是否应用fillBefore值,对fillAfter值无影响,默认为true
android:repeatMode= “restart” // 选择重复播放动画模式,restart代表正序重放,reverse代表倒序回放,默认为restart|
android:repeatCount = “0” // 重放次数(所以动画的播放次数=重放次数+1),为infinite时无限重复
android:interpolator = @[package:]anim/interpolator_resource // 插值器,即影响动画的播放速度,下面会详细讲
-->
java代码
public void btn1(View view) {
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.bianhua);
animator.setTarget(btn1);
animator.start();
}
使用 ObjectAnimator 实现四种动画
这里我打算通过使用 ObjectAnimator 实现四大动画框架:
alpha
scaleX/scaleY
translateX/translateY
rotation
java 代码
public void btn2(View view) {
// final ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "alpha", 0, 1);
// ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "translationX", 0, 200);
// ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "translationY", 0, 200, 100);
// ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "scaleX", 1, 5);
// ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "scaleY", 1, 5);
// ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "rotation", 0, 270);
ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "rotationY", 0, 180, -100);
animator.setDuration(2000);
animator.setRepeatCount(2);
animator.setInterpolator(new AccelerateInterpolator());
// animator.setInterpolator(new DecelerateInterpolator());
animator.setRepeatMode(ValueAnimator.RESTART);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
}
});
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.start();
}
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):参数中的动画同时执行
java 代码
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(3000);
animatorSet.setInterpolator(new LinearInterpolator());
ObjectAnimator translationX = ObjectAnimator.ofFloat(btn, "translationX", 0, 300);
ObjectAnimator rotation = ObjectAnimator.ofFloat(btn, "rotation", 0, 720);
ObjectAnimator scaleX = ObjectAnimator.ofFloat(btn, "scaleX", 1, 5);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(btn, "scaleY", 1, 5);
ObjectAnimator alpha = ObjectAnimator.ofFloat(btn, "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动画
介绍
https://www.jianshu.com/p/47b0ae970dd5
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();
});
}
属性动画参考链接
https://blog.csdn.net/harvic880925/article/details/50598322