2017-03-02 86 views
0

我得到一個片段,它有一個名爲RingProgress的控件,它只是一個根據給定的百分比值填充自身的環。例如,如果我這樣做:當試圖設置隨時間變化的值時,Android視圖不會更新

ringProgress.setProgress(20); 

這意味着20%的戒指現在會被填滿。

我想要做的是動畫環充滿幾秒鐘。所以我試圖做的是這樣的:

@Override 
public void onResume() 
{ 
    super.onResume(); 
    HandlerThread handlerThread = new HandlerThread("countdown"); 
    handlerThread.start(); 
    Handler handler = new Handler(handlerThread.getLooper()); 
    handler.post(new Runnable() 
    { 
     @Override 
     public void run() 
     { 
      final Timer timer = new Timer(); 
      timer.scheduleAtFixedRate(new TimerTask() 
      { 
       int totalSeconds = secondsToStart + minutesToStart * 60; 
       int secondsPassed = 0; 

       @Override 
       public void run() 
       { 
        if(secondsPassed == totalSeconds) 
        { 
         timer.cancel(); 
        } 
        final int currentProgress = (secondsPassed/totalSeconds) * 100; 
        secondsPassed++; 
        getActivity().runOnUiThread(new Runnable() 
        { 
         @Override 
         public void run() 
         { 
          mRingProgressBar.setProgress(currentProgress); 
         } 
        }); 

       } 
      }, 0, 1000); 

     } 
    }); 
} 

問題是直到時間到了才顯示環的更新。例如,如果我將它設置爲5秒,那麼當碎片加載時,戒指設置爲0,則5秒鐘內沒有任何反應,然後戒指一次性全部100%。

我該如何啓動這個動畫合適嗎?

+0

你申請記錄/斷點,看看是否一切叫什麼名字? – dumazy

+0

'ringProgress.setProgress(20); '只有當你設置'ringProgress.setMax(100)'時,纔會有20%'; – Idan

+1

這是通過處理程序執行的強制嗎? –

回答

1

而不是使用一個處理程序,您可以使用屬性動畫如下:

ObjectAnimator.ofInt(mRingProgressBar, "progress", 0, 100) 
    .setDuration(totalSeconds * 1000) //time is in miliseconds 
    .start(); 

這將在您的mRingProgressBar中找到一個方法setProgress()並根據極限值設置值給出。在上面的例子中,0到100 你可以閱讀更多關於它here

3

我想這個問題是

final int currentProgress = (secondsPassed/totalSeconds) * 100; 

secondsPassed/totalSeconds返回int值,因此將只有0或1。而你是乘到100

你必須使用floatdouble代替

final int currentProgress = Math.round(((float) secondsPassed)/((float) totalSeconds)*100f); 
+0

這可以解釋爲什麼只在最後更新進度 – dumazy

+1

也可以執行'secondsPassed * 100/totalSeconds'這將導致相同的事情,而不需要投所有的數字。另外,如果其中一個值爲'float',則不需要轉換其他值,這意味着如果您已經有'(float)secondsPassed',則不需要'(float)totalSeconds'和'100f'。 –

+0

@Yonatan Nir,雖然這看起來像是確切的問題,但由於處理程序的使用不正確,您的代碼不可靠。看到我的答案。 – azizbekian

2

在此行中:

Handler handler = new Handler(handlerThread.getLooper()); 

你試圖讓從handlerThread彎針。但你已經初始化了你的活套嗎?

getLooper()

此方法的文檔返回與此線程相關聯的活套。如果此線程未啓動或出於任何原因isAlive()返回false,則此方法將返回null。如果這個線程已經啓動,這個方法會阻塞,直到活套已經初始化。

onLooperPrepared()是回調,在那裏你可以肯定的,那Looper已初始化,因此你可以構造上的邏輯。

因此,你需要做的,是子類HandlerThread,並從onLooperPrepared()回調創建適當的邏輯。

Here's a nice post這將幫助你。在那裏看到MyWorkerThread類的實現。

+0

雖然這不是問題,但我認爲它是一個大拇指,因爲它是一件重要的事情 –

0

既然你要在不同的線程運行,您可以使用此處理在類的頂部:

 private int progress = 0; 
    Handler timerHandler = new Handler(); 
    Runnable timerRunnable = new Runnable() { 
      @Override 
      public void run() { 

      ringProgress.setProgress(progress); 
      progress += 20; 
      if (progress == 100) { //clear?? 
      } 
      timerHandler.postDelayed(this, 1000); 
     } 
    }; 

inCreate設置最大:

ringProgress.setMax(100); 

這將完成5秒內動畫,然後你可以清除動畫。如果你想要更小的增量,改變以下(更新每隔十分之一秒)的線,並更改步驟

timerHandler.postDelayed(this, 100);