2015-03-02 10 views
16

Tôi đã tạo ra một AnimatedVectorDrawable, nó hoạt động khá tốt, bây giờ tôi đang tìm kiếm một cách để thay đổi hình ảnh động hoặc ẩn xem sau khi nó kết thúc. Tôi đã hy vọng có một người nghe nhưng nó không giống như có. Ai đó có thể giúp đỡ?Có cách nào để nghe cho hết hình ảnh động trong AnimatedVectorDrawables

EDIT

Vì vậy, tôi tìm thấy một workaround, nhưng không phải là một cách rất thanh lịch. Những gì tôi đã làm là tạo một chuỗi và thăm dò ý kiến ​​nếu hoạt ảnh đang chạy.

new Runnable() { 
    public void run() { 
     while(mLoop) { 
      if(mAnimatedVectorDrawable.isRunning()) { 
       Thread.sleep(mPollingInterval); 
      } else { 
       mLoop = false; 
       // TODO what ever 
      } 
     } 
    } 
}; 

Nếu ai đó tìm được giải pháp tốt hơn, vui lòng chia sẻ.

+0

Off the cuff, tôi nghĩ rằng bạn sẽ cần đến ngã ba nó, để có được quyền truy cập! cho các trường hợp 'Animator' và có thể đăng ký người nghe cho những người đó – CommonsWare

+0

Cảm ơn, nhưng tôi đã hy vọng điều gì đó đơn giản hơn một chút –

+1

Tôi đã gửi yêu cầu tính năng cho điều này: https://code.google.com/p/android/ các vấn đề/chi tiết? id = 158780 – CommonsWare

Trả lời

6

bản năng đầu tiên của tôi là để lấy mã nguồn, thêm một số callbacks, và tạo ra một drawable tùy chỉnh ra khỏi nó. Tất nhiên, điều đó có nghĩa là không hỗ trợ xml.

Nó chỉ ra rằng AnimatedVectorDrawable sử dụng phương pháp riêng tư VectorDrawable's. Vì vậy, cách tiếp cận này sẽ không hoạt động.

Chúng ta có thể tạo ra một lớp wrapper đơn giản xung quanh AnimatedVectorDrawable và thêm callbacks:

public class AVDWrapper { 

    private Handler mHandler; 
    private Animatable mDrawable; 
    private Callback mCallback; 
    private Runnable mAnimationDoneRunnable = new Runnable() { 

     @Override 
     public void run() { 
      if (mCallback != null) 
       mCallback.onAnimationDone(); 
     } 
    }; 

    public interface Callback { 
     public void onAnimationDone(); 
     public void onAnimationStopped(); 
    } 

    public AVDWrapper(Animatable drawable, 
          Handler handler, Callback callback) { 
     mDrawable = drawable; 
     mHandler = handler; 
     mCallback = callback; 
    } 

    // Duration of the animation 
    public void start(long duration) { 
     mDrawable.start(); 
     mHandler.postDelayed(mAnimationDoneRunnable, duration); 
    } 

    public void stop() { 
     mDrawable.stop(); 
     mHandler.removeCallbacks(mAnimationDoneRunnable); 

     if (mCallback != null) 
      mCallback.onAnimationStopped(); 
    } 
} 

Mã của bạn sẽ trông như thế:

final Drawable drawable = circle.getDrawable(); 
final Animatable animatable = (Animatable) drawable; 

AVDWrapper.Callback callback = new AVDWrapper.Callback() { 
     @Override 
     public void onAnimationDone() { 
      tick.setAlpha(1f); 
     } 

     @Override 
     public void onAnimationStopped() { 
      // Okay 
     } 
    }; 

AVDWrapper avdw = new AVDWrapper(animatable, mHandler, callback); 
//animatable.start(); 
avdw.start(2000L); 

tick.setAlpha(0f); 
//tick.animate().alpha(1f).setStartDelay(2000).setDuration(1).start(); 

// One wrapper is sufficient if the duration is same 
final Drawable drawable2 = tick.getDrawable(); 
final Animatable animatable2 = (Animatable) drawable2; 
animatable2.start(); 

Nhưng, đây là chính xác những gì bạn đang làm với setStartDelay. Vì vậy, tôi không biết làm thế nào hữu ích này sẽ được.

Edit: Tất cả điều này cũng có thể được thực hiện bên trong một AnimatedVectorDrawable mở rộng. Tuy nhiên, bạn sẽ mất hoàn toàn hỗ trợ xml.

0

Tôi đã tìm thấy cùng một vấn đề. Tôi đang cố gắng tạo ra một vòng tròn được vẽ và đánh dấu vào bên trong.

Điều tốt nhất tôi có thể làm là chơi với thời lượng. Một cái gì đó như thế này:

final Drawable drawable = circle.getDrawable(); 
final Animatable animatable = (Animatable) drawable; 
animatable.start(); 

tick.setAlpha(0f); 
tick.animate().alpha(1f).setStartDelay(2000).setDuration(1).start(); 
final Drawable drawable2 = tick.getDrawable(); 
final Animatable animatable2 = (Animatable) drawable2; 
animatable2.start(); 

Nó sẽ là tuyệt vời để có một người biết lắng nghe

3

Thật kỳ lạ là không có API trực tiếp để nhận được điều này. Tôi cho rằng cách giải quyết không liên quan đến ghi đè sẽ chỉ đơn giản là tìm hoạt ảnh trong tập hợp hoạt ảnh của bạn mất nhiều thời gian nhất, sau đó đăng runnable bị trì hoãn để ẩn chế độ xem.

int longestAnimationTime = 500; //miliseconds, defined in XML possibly? 
drawable.start(); 
drawableView.postDelayed(new Runnable() { 

     @Override 
     public void run() { 
      drawableView.setVisibility(View.GONE); 
     } 
}, longestAnimationTime); 

Nhược điểm là nó liên quan đến cứng mã hóa thời gian hoạt hình dài nhất của bạn, nhưng miễn là bạn đang tham khảo các giá trị không đổi cùng cả trong XML hoạt hình và trong mã, nó sẽ hoạt động chính xác, không ghi đè cần thiết.

7

Không cố gắng này được nêu ra nhưng Android 6.0 có một phương pháp registerAnimationCallback từ giao diện Animatable2 cho

Chỉnh sửa này: yep này hoạt động trong Android 6.0 giả lập:

mAnimatedVectorDrawable.registerAnimationCallback (new Animatable2.AnimationCallback(){ 
    public void onAnimationEnd(Drawable drawable){ 
     //Do something 
    } 
} 

Edit2: trông giống như họ thiên đường' t thêm hỗ trợ cho điều này trong AnimatedVectorDrawableCompat từ hỗ trợ lib 23.2+ :(

Edit3: nó trông như thế này đã được thêm vào trong hỗ trợ lib 25.3.0

Cảm ơn Carson

+1

Điều này hiện hoạt động với các thư viện hỗ trợ mới nhất xuống API 14 https://stackoverflow.com/a/46459743/4672107 –

Các vấn đề liên quan