日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

lottie android min sdk,跳一个Lottie无法回调开始播放动画事件的坑

發布時間:2023/12/2 编程问答 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 lottie android min sdk,跳一个Lottie无法回调开始播放动画事件的坑 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、背景介紹

項目背景是在界面中彈出一個浮層動畫,同時播放一個音效。

二、當前實現

實現思路比較簡單:繼承一個DialogFragment,在相關的生命周期方法onViewCreated中調用startLottieAnim進行動畫播放,同時監聽lottie動畫播放的回調事件,在動畫開始播放時播放音效文件;動畫播放結束時關閉DialogFragment。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29private void startLottieAnim(String assetFolder, final Uri voiceUri){

lottieAnimationView.setImageAssetsFolder(assetFolder + "/images");

lottieAnimationView.setAnimation(assetFolder + "/anim.json");

lottieAnimationView.setRepeatCount(0);

lottieAnimationView.addAnimatorListener(new Animator.AnimatorListener() {

@Override

public void onAnimationStart(Animator animation){

playAnimVoice(voiceUri);

}

@Override

public void onAnimationEnd(Animator animation){

stopAnimVoice();

dismiss();

}

@Override

public void onAnimationCancel(Animator animation){

stopAnimVoice();

dismiss();

}

@Override

public void onAnimationRepeat(Animator animation){

playAnimVoice(voiceUri);

}

});

lottieAnimationView.playAnimation();

}

三、發現問題

對于以上的代碼,實際運行起來會發現動畫播放的同時并不能播放音頻,而且播放結束也不會自動消失。也就是說onAnimationStart和onAnimationEnd方法并沒有被回調。這是為什么呢?看lottie實現源碼 (BaseLottieAnimator),會發現

1

2

3

4

5

6

7

8

9void notifyStart(boolean isReverse){

for (Animator.AnimatorListener listener : listeners) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

listener.onAnimationStart(this, isReverse);

} else {

listener.onAnimationStart(this);

}

}

}

1

2

3

4

5

6

7

8void notifyEnd(boolean isReverse){

for (Animator.AnimatorListener listener : listeners) {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

listener.onAnimationEnd(this, isReverse);

} else {

listener.onAnimationEnd(this);

}

}

在通知動畫開始和結束的時候,會根據系統版本決定走哪個方法,這里需要注意方法簽名。由于之前代碼只寫了一個參數的方法回調,因此在Android O及以上版本中會走另一個方法回調。因此,首先想到需要在注冊的AnimatorListener中添加之前遺漏的兩個方法回調。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40{

lottieAnimationView.setImageAssetsFolder(assetFolder + "/images");

lottieAnimationView.setAnimation(assetFolder + "/anim.json");

lottieAnimationView.setRepeatCount(0);

lottieAnimationView.addAnimatorListener(new Animator.AnimatorListener() {

@Override

public void onAnimationStart(Animator animation){

playAnimVoice(voiceUri);

}

@Override

public void onAnimationStart(Animator animation, boolean isReverse){

playAnimVoice(voiceUri);

}

@Override

public void onAnimationEnd(Animator animation){

stopAnimVoice();

dismiss();

}

@Override

public void onAnimationEnd(Animator animation, boolean isReverse){

stopAnimVoice();

dismiss();

}

@Override

public void onAnimationCancel(Animator animation){

stopAnimVoice();

dismiss();

}

@Override

public void onAnimationRepeat(Animator animation){

playAnimVoice(voiceUri);

}

});

lottieAnimationView.playAnimation();

}

修改之后運行會發現,動畫播放結束的回調事件成功接收了,但是音效依然無法播放。也就是onAnimationStart方法依然未被回調。繼續看下源碼:在LottieAnimationView.java中

1

2

3

4

5

6

7

8public void playAnimation(){

if (isShown()) {

lottieDrawable.playAnimation();

enableOrDisableHardwareLayer();

} else {

wasAnimatingWhenNotShown = true;

}

}

如果isShown判斷成功,會繼續走LottieDrawable.java中的

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18public void playAnimation(){

if (compositionLayer == null) {

lazyCompositionTasks.add(new LazyCompositionTask() {

@Override

public void run(LottieComposition composition){

playAnimation();

}

});

return;

}

if (systemAnimationsEnabled || getRepeatCount() == 0) {

animator.playAnimation();

}

if (!systemAnimationsEnabled) {

setFrame((int) (getSpeed() < 0 ? getMinFrame() : getMaxFrame()));

}

}

進而走到LottieValueAnimator.java中的playAnimation

1

2

3

4

5

6

7

8

9@MainThread

public void playAnimation(){

running = true;

notifyStart(isReversed());

setFrame((int) (isReversed() ? getMaxFrame() : getMinFrame()));

lastFrameTimeNs = 0;

repeatCount = 0;

postFrameCallback();

}

在這里看到了熟悉的notifyStart方法。可是我們并沒有收到對應的回調,可以想到LottieAnimationView.java中并沒有走isShown判斷分支,也就是說走了

1

2

3

4

5

6

7

8public void playAnimation(){

if (isShown()) {

lottieDrawable.playAnimation();

enableOrDisableHardwareLayer();

} else {

wasAnimatingWhenNotShown = true;

}

}

只是標記了一個狀態,標明lottie動畫還未顯示出來。那它為什么后來又能播放動畫呢?在LottieAnimationView.java中有監聽可見性回調的方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19protected void onVisibilityChanged(@NonNull View changedView, int visibility){

// This can happen on older versions of Android because onVisibilityChanged gets called from the

// constructor of View so this will get called before lottieDrawable gets initialized.

// https://github.com/airbnb/lottie-android/issues/1143

if (lottieDrawable == null) {

return;

}

if (isShown()) {

if (wasAnimatingWhenNotShown) {

resumeAnimation();

wasAnimatingWhenNotShown = false;

}

} else {

if (isAnimating()) {

pauseAnimation();

wasAnimatingWhenNotShown = true;

}

}

}

當lottieview從不可見到可見時,會根據wasAnimatingWhenNotShown之前記錄的這個狀態去resumeAnimation。在resumeAnimation方法一路跟下去最后會走到LottieValueAnimator.java的

1

2

3

4

5

6

7

8

9

10public void resumeAnimation(){

running = true;

postFrameCallback();

lastFrameTimeNs = 0;

if (isReversed() && getFrame() == getMinFrame()) {

frame = getMaxFrame();

} else if (!isReversed() && getFrame() == getMaxFrame()) {

frame = getMinFrame();

}

}

這里可以發現并沒有像startAnimation那樣的notifyXXX的回調方法了。因此我們收不到onAnimationStart的方法回調了。

至此弄清楚了異常的原因,如何修改就很簡單了。現在已經能猜到是布局加載之后,lottieview還沒有渲染出來我們就去startAnimation導致回調無法走到,因此我們可以通過對lottieView進行post或者通過監聽viewTreeObserver的事件再進行startPlayAnimation操作就行了。

四、總結

1、回調方法要寫完整;

2、如果彈框一開始就要顯示lottie動畫,需要等ui控件可見之后再播放動畫

總結

以上是生活随笔為你收集整理的lottie android min sdk,跳一个Lottie无法回调开始播放动画事件的坑的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。