Android 動(dòng)畫(huà) Lottie 如何使用
一、簡(jiǎn)介
Lottie 是Airbnb開(kāi)源的一個(gè)面向 iOS、Android、React Native 的動(dòng)畫(huà)庫(kù),能分析 Adobe After Effects 導(dǎo)出的動(dòng)畫(huà),并且能讓原生 App 像使用靜態(tài)素材一樣使用這些動(dòng)畫(huà),完美實(shí)現(xiàn)動(dòng)畫(huà)效果。
二、Lottie動(dòng)畫(huà)文件制作
1.讓設(shè)計(jì)師使用Adobe 的 After Effects(簡(jiǎn)稱 AE)工具(美工一般都會(huì)這個(gè))制作這個(gè)動(dòng)畫(huà)。
2.在AE中安裝一個(gè)叫做Bodymovin的插件。下載?bodymovin,解壓縮后只需要\build\extension\bodymovin.zxp這個(gè)檔案就可以
3.手動(dòng)安裝plugin,以windows系統(tǒng)而言,要先下載 **ExMan Command Line tool?**并解壓縮。 再來(lái)把下載的bodymovin壓縮后的 bodymovin-master\build\extension 目錄下的bodymovin.zxp 這個(gè)檔案復(fù)制進(jìn)去同一個(gè)資料夾。
4.去找cmd,并以系統(tǒng)管理員身分執(zhí)行。
5.打“cd C:/ExManCmd_win?所在的路徑“,進(jìn)入ExManCmd的資料夾中
6.接著打 ExManCmd.exe /install bodymovin.zxp 就完
7.再來(lái)進(jìn)入AE 后,可以在windows/extentions/bodymovin 找到插件,開(kāi)啟后按下Render 就完成了。?重點(diǎn)來(lái)了,這時(shí)會(huì)在你選的Destination Folder目錄中生成一個(gè)json格式的文件,這個(gè) json 文件描述了該動(dòng)畫(huà)的一些關(guān)鍵點(diǎn)的坐標(biāo)以及運(yùn)動(dòng)軌跡。
三、如何使用Lottie
Lottie支持多平臺(tái),使用同一個(gè)JSON動(dòng)畫(huà)文件,可在不同平臺(tái)實(shí)現(xiàn)相同的效果。支持Android,ios,前段。
1.依賴
在項(xiàng)目的 build.gradle 文件添加依賴
dependencies {
compile 'com.airbnb.android:lottie:2.1.0'
}
2.動(dòng)畫(huà)文件
第一種方法,將我們所需要的動(dòng)畫(huà)文件loading.json保存在app/src/main/assets文件里。 第二種方法,網(wǎng)絡(luò)上AE生成的動(dòng)畫(huà)文件。
3.使用
在布局文件中使用
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/animation_view"
android:layout_width="400dp"
android:layout_height="400dp"
app:lottie_fileName="loading.json"
app:lottie_loop="true"
app:lottie_autoPlay="true"/>
使用網(wǎng)絡(luò)加載AE生成的動(dòng)畫(huà)文件json
private void loadUrl(String url) {
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
try {
JSONObject json = new JSONObject(response.body().string());
LottieComposition.Factory
.fromJson(getResources(), json, new OnCompositionLoadedListener() {
@Override
public void onCompositionLoaded(LottieComposition composition) {
setComposition(composition);
}
});
} catch (JSONException e) {
}
}
}
});
}
private void setComposition(LottieComposition composition){
animation_view.setProgress(0);
animation_view.loop(true);
animation_view.setComposition(composition);
animation_view.playAnimation();
}
四、Lottie實(shí)現(xiàn)原理
設(shè)計(jì)師把一張復(fù)雜的圖片使用多個(gè)圖層來(lái)表示,每個(gè)圖層展示一部分內(nèi)容,圖層中的內(nèi)容也可以拆分為多個(gè)元素。拆分元素之后,根據(jù)動(dòng)畫(huà)需求,可以單獨(dú)對(duì)圖層或者圖層中的元素做平移、旋轉(zhuǎn)、收縮等動(dòng)畫(huà)。
Lottie的使用的資源是需要先通過(guò)bodymovin( bodymovin 插件本身是用于網(wǎng)頁(yè)上呈現(xiàn)各種AE效果的一個(gè)開(kāi)源庫(kù))將 Adobe After Effects (AE)生成的aep動(dòng)畫(huà)工程文件轉(zhuǎn)換為通用的json格式描述文件。Lottie則負(fù)責(zé)解析動(dòng)畫(huà)的數(shù)據(jù),計(jì)算每個(gè)動(dòng)畫(huà)在某個(gè)時(shí)間點(diǎn)的狀態(tài),準(zhǔn)確地繪制到屏幕上。
Lottie主要類圖:
Lottie對(duì)外通過(guò)控件LottieAnimationView暴露接口,控制動(dòng)畫(huà)。
LottieAnimationView繼承自ImageView,通過(guò)當(dāng)前時(shí)間繪制canvas顯示到界面上。這里有兩個(gè)關(guān)鍵類:LottieComposition 負(fù)責(zé)解析json描述文件,把json內(nèi)容轉(zhuǎn)成Java數(shù)據(jù)對(duì)象;LottieDrawable負(fù)責(zé)繪制,把LottieComposition轉(zhuǎn)成的數(shù)據(jù)對(duì)象繪制成drawable顯示到View上。順序如下:
解析json外部結(jié)構(gòu)LottieComposition封裝整個(gè)動(dòng)畫(huà)的信息,包括動(dòng)畫(huà)大小,動(dòng)畫(huà)時(shí)長(zhǎng),幀率,用到的圖片,字體,圖層等等。
{
"v": "4.6.0", //bodymovin的版本
"fr": 29.9700012207031, //幀率
"ip": 0, //起始關(guān)鍵幀
"op": 141.000005743048, //結(jié)束關(guān)鍵幀
"w": 800, //動(dòng)畫(huà)寬度
"h": 800, //動(dòng)畫(huà)高度
"ddd": 0,
"assets": [...] //資源信息
"layers": [...] //圖層信息
}
解析圖片資源
"assets": [ //資源信息
{ //第一張圖片
"id": "image_0", //圖片id
"w": 58, //圖片寬度
"h": 31, //圖片高度
"u": "images/", //圖片路徑
"p": "img_0.png" //圖片名稱
},
{...} //第n張圖片
]
解析圖層
"layers": [ //圖層信息
{ //第一層動(dòng)畫(huà)
"ddd": 0,
"ind": 0, //layer id 圖層 id
"ty": 4, //圖層類型
"nm": "center_circle",
"ks": {...}, //動(dòng)畫(huà)
"ao": 0,
"shapes": [...],
"ip": 0, //inFrame 該圖層起始關(guān)鍵幀
"op": 90, //outFrame 該圖層結(jié)束關(guān)鍵幀
"st": 0, //startFrame 開(kāi)始
"bm": 0,
"sr": 1
},
{...} //第n層動(dòng)畫(huà)
]
如何動(dòng)起來(lái)時(shí)序圖
利用屬性動(dòng)畫(huà)控制進(jìn)度,每次進(jìn)度改變通知到每一層,觸發(fā)LottieAnimationView重繪。代碼如下:
public LottieDrawable() {
animator.setRepeatCount(0);
animator.setInterpolator(new LinearInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if (systemAnimationsAreDisabled) {
animator.cancel();
setProgress(1f);
} else {
setProgress((float) animation.getAnimatedValue());
}
}
});
}
通過(guò)CompositionLayer把進(jìn)度傳遞到各個(gè)圖層
@Override
public void setProgress(@FloatRange(from = 0f, to = 1f) float progress) {
super.setProgress(progress);
if (timeRemapping != null) {
long duration = lottieDrawable.getComposition().getDuration();
long remappedTime = (long) (timeRemapping.getValue() * 1000);
progress = remappedTime / (float) duration;
}
if (layerModel.getTimeStretch() != 0) {
progress /= layerModel.getTimeStretch();
}
progress -= layerModel.getStartProgress();
for (int i = layers.size() - 1; i >= 0; i--) {
layers.get(i).setProgress(progress);
}
}
通知進(jìn)度改變
void setProgress(@FloatRange(from = 0f, to = 1f) float progress) {
if (progress < getStartDelayProgress()) {
progress = 0f;
} else if (progress > getEndProgress()) {
progress = 1f;
}
if (progress == this.progress) {
return;
}
this.progress = progress;
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).onValueChanged();
}
}
最終回調(diào)到LottieAnimationView的invalidateDrawable
@Override
public void invalidateDrawable(@NonNull Drawable dr) {
if (getDrawable() == lottieDrawable) {
// We always want to invalidate the root drawable so it redraws the whole drawable.
// Eventually it would be great to be able to invalidate just the changed region.
super.invalidateDrawable(lottieDrawable);
} else {
// Otherwise work as regular ImageView
super.invalidateDrawable(dr);
}
}
最后觸發(fā)LottieDrawable重繪
@Override
public void draw(@NonNull Canvas canvas) {
...
matrix.reset();
matrix.preScale(scale, scale);
compositionLayer.draw(canvas, matrix, alpha); //這里會(huì)調(diào)用所有l(wèi)ayer的繪制方法
if (hasExtraScale) {
canvas.restore();
}
}
總結(jié)
1.劣勢(shì)
(1)性能不夠好—某些動(dòng)畫(huà)特效,內(nèi)存和性能不夠好;相對(duì)于屬性動(dòng)畫(huà),在展示大動(dòng)畫(huà)時(shí),幀率較低文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-858386.html
2.優(yōu)勢(shì)
(1)開(kāi)發(fā)效率高—代碼實(shí)現(xiàn)簡(jiǎn)單,更換動(dòng)畫(huà)方便,易于調(diào)試和維護(hù)。
(2)數(shù)據(jù)源多樣性—可從assets,sdcard,網(wǎng)絡(luò)加載動(dòng)畫(huà)資源,能做到不發(fā)版本,動(dòng)態(tài)更新
(3)跨平臺(tái)—設(shè)計(jì)稿導(dǎo)出一份動(dòng)畫(huà)描述文件,android,ios,react native通用
(4) Lottie使用簡(jiǎn)單,易于上手,非常值得嘗試。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-858386.html
到了這里,關(guān)于Android 動(dòng)畫(huà) Lottie 如何使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!