Android SVG和Lottie库播放动画(Json)
AE-----→Json
安卓调用.json文件
SVG是Android 5.0中新加入的一个新特性。
从5.0开始android也开始支持SVG图了,这使得我们可以实现更多的好看的动画。
SVG的全称是Scalable Vector Graphics,叫可缩放矢量图形。它和位图(Bitmap)相对,SVG不会像位图一样因为缩放而让图片质量下降。下面这个图片展示了SVG和位图的区别,左边的位图在放大后出现了锯齿,而右边的SVG任然清晰。
可以用SVG图片直接转换成Android可用格式。
我们可以通过上面的变动手动把普通SVG转成android用的VectorDrawable,或者我们可以用这个网站自动完成转换 http://inloop.github.io/svg2android/
自己使用代码制作。
用下面的列子来介绍相关的标签
vector_drawable.xml
<vector xmlns:android="http://schemas.android.com/apk/res/ android"
android:width="200dp"
android:height="200dp"
android:viewportHeight="1000"
android:viewportWidth="1000">
<group
android:name="rotation"
android:pivotX="500.0"
android:pivotY="500.0"
android:rotation="0.0">
<path
android:name="vector"
android:fillColor="#00ffff"
android:pathData="M67,750 L500,0 500,0 933,750 67,750 M146,853 A 0.1,500 0 0 1 146,148 M146,148 A 500,0.1 0 0 1 851,148 M851,148 A 0.1,500 0 0 1 851,853 M851,853 A 500,0.1 0 0 1 146,853" />
group>
vector>
注意到和普通SVG图内容不同地方在与viewBox那变成了 viewportWidth, viewportHeight .
viewportWidth , viewportHeight 就相当于画这个SVG的画布大小。
width和height是规定这个SVG图像最终的显示大小的,一般用dp表示。
第二个不同是有一个普通SVG里的fill到android里要变成fillColor,这里就是SVG图像填充的颜色。
第三点不同是,普通SVG的path的数据是d开头的标签,在android里要写成pathData。
综上所述,只要把viewBox的大小改成viewport的大小,把填充颜色的fill改成fillColor,把Path中的d,改成pathData就行了。
android:name="rotation" 为group 和 path 加上 name 属性 是为了后面能便于加上动画。
android:pathData="M67,750 L500,0 500,0 933,750 67,750 M146,853 A 0.1,500 0 0 1 146,148 M146,148 A 500,0.1 0 0 1 851,148 M851,148 A 0.1,500 0 0 1 851,853 M851,853 A 500,0.1 0 0 1 146,853"
M = moveto 相当于 android Path 里的moveTo(),用于移动起始点
L = lineto 相当于 android Path 里的lineTo(),用于画线
H = horizontal lineto 用于画水平线
V = vertical lineto 用于画竖直线
C = curveto 相当于cubicTo(),三次贝塞尔曲线
S = smooth curveto 同样三次贝塞尔曲线,更平滑
Q = quadratic Belzier curve quadTo(),二次贝塞尔曲线
T = smooth quadratic Belzier curveto 同样二次贝塞尔曲线,更平滑
A = elliptical Arc 相当于arcTo(),用于画弧
Z = closepath 相当于closeTo(),关闭path
"250dp"
android:layout_height="300dp"
android:src="@drawable/vector_drawable"
android:id="@+id/iv_main"/>
animated-vector 可以去创建一个矢量资源的动画。
同样的,创建出来的 vector_animation.xml 放置在 drawable 下。
animated-vector.xml
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vector_drawable" >
<target
android:name="vector"
android:animation="@anim/vector_anim" />
<target
android:name="rotation"
android:animation="@anim/vector_rotation" />
animated-vector>
android:drawable="@drawable/vector_drawable" 设置矢量资源文件。
target 设置动画,第一个为 @drawable/vector_drawable 下 name 为 vector 设置 动画。第二个 同理。
以下是动画效果文件: (动画文件放置在 anim 文件目录下)
vector_anim.xml 这个是制作了一个变形动画
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="M67,750 L500,0 500,0 933,750 67,750 M146,853 A 0.1,500 0 0 1 146,148 M146,148 A 500,0.1 0 0 1 851,148 M851,148 A 0.1,500 0 0 1 851,853 M851,853 A 500,0.1 0 0 1 146,853"
android:valueTo="M147,853 L147,147 853,147 853,853 147,853 M146,853 A 0.1,500 0 0 1 146,148 M146,148 A 500,0.1 0 0 1 851,148 M851,148 A 0.1,500 0 0 1 851,853 M851,853 A 500,0.1 0 0 1 146,853"
android:valueType="pathType" />
<objectAnimator
android:startOffset="3000"
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="M147,853 L147,147 853,147 853,853 147,853 M147,853 A 0.1,500 0 0 1 147,147 M147,147 A 500,0.1 0 0 1 853,147 M853,147 A 0.1,500 0 0 1 853,853 M851,853 A 500,0.1 0 0 1 147,853"
android:valueTo="M147,853 L147,147 853,147 853,853 147,853 M147,853 A 500,500 0 0 1 147,147 M147,147 A 500,500 0 0 1 853,147 M853,147 A 500,500 0 0 1 853,853 M853,853 A 500,500 0 0 1 147,853"
android:valueType="pathType" />
set>
vector_rotation.xml 这个是制作了一个旋转动画
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="6000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="1440" />
set>
使用该动画:
"250dp"
android:layout_height="300dp"
android:src="@drawable/vector_animation"
android:id="@+id/iv_main"/>
开启动画的代码:
final ImageView iv = (ImageView) findViewById(R.id.iv_main);
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(iv.getDrawable() instanceof Animatable){
//开始动画
((Animatable) iv.getDrawable()).start();
}
}
});
效果如下:
Android 5.x 之后提供了对 SVG 的支持,通过 VectorDrawable、AnimatedVectorDrawable 的结合可以实现一些稍微复杂的动画,但是兼容性是一个问题,不过整个实现流程非常麻烦,每次全新实现一个动画都得重头来过,最最关键的是,如果一个公司下的 App,iOS 也要实现一套一样的动画,资源的占用就显得过大了。
而 Airbnb 开源的这个项目完美的解决以上难题
假设我们要做一个引导页面的欢迎动画,这个一般设计师会用 Adobe 旗下的 After Effects (简称 AE)来做个动画出来,设计师用 AE 做个动画比工程师用代码去实现一个动画要快的多的多,调整起来也很方便,之后 AE 上有一款插件叫做 Bodymovin,这个插件也比较屌,可以直接根据 AE 上的动画文件导出 json 文件,这个 json 文件描述了该动画的一些关键点的坐标以及运动轨迹,之后我们在项目中引用 Lottie 开源库,在布局文件中简单的加上这么一句就完美的实现了。
dependencies {
compile 'com.airbnb.android:lottie:1.0.1'
...
}
Lottie 支持Jellybean (API 16)及以上的系统,使用这个Lottie应该把 xxxxx.json 文件放在 app/src/main/assets 目录下。
以下例子中把O.json文件放在规定的目录下。
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animation_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:lottie_fileName="O.json"
app:lottie_loop="true"
app:lottie_autoPlay="true" />
布局文件中:
id="@+id/animation_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
-----------------------------------------------------
代码中:
LottieAnimationView animationView = (LottieAnimationView) findViewById(R.id.animation_view);
animationView.setAnimation("O.json");
//设置是否循环播放
animationView.loop(true);
//播放动画
animationView.playAnimation();
注意的是:这方法将在后台线程异步加载数据文件,并在加载完成后开始渲染显示动画.
效果如图:
animationView.addAnimatorUpdateListener((animation) -> {
// Do something.
});
btnStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//animationView.isAnimating()动画是否在播放
if (animationView.isAnimating()) {
//动画停止
animationView.cancelAnimation();
}
}
});
final LottieDrawable drawable = new LottieDrawable();
LottieComposition.fromAssetFileName(this, "O.json", new LottieComposition.OnCompositionLoadedListener() {
@Override
public void onCompositionLoaded(LottieComposition composition) {
drawable.setComposition(composition);
drawable.loop(true);
drawable.playAnimation();
}
});
animationView.setAnimation("O.json", LottieAnimationView.CacheStrategy.Strong);
public enum CacheStrategy {
None,
Weak,
Strong
}
其中CacheStrategy的值可以是Strong,Weak或者None,它们用来决定LottieAnimationView对已经加载并转换好的动画持有怎样形式的引用(强引用/弱引用).