2014-09-26 41 views
1

我正在使用GridView在4列表中顯示單詞列表。我的自定義適配器的getView方法會檢查單詞的寬度,如果不合適,會將其縮小。它使用遞歸檢查來執行此操作,該檢查不斷縮放文本,直到它適合Android:從While循環內的適配器更新UI

private void shrinkText(final TextView wv, final String word) { 
    wv.setTextSize(defaultTextSize); 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      while (wv.getWidth()>0 && wv.getPaint().measureText(word) > wv.getWidth()) { 
       Logg.d("word too big. Shrink from " + wv.getTextSize()/density + " to " + (wv.getTextSize()/density-1.0f)); 
       wv.setTextSize(wv.getTextSize()/density - 1.0f); 
      } 
     } 
    }).start(); 
} 

因爲我使用的是一個while循環,所以我使用了一個新的線程來保護ANR,避免出現無限循環的情況。這是奇怪的事情:有時它很好。然後有時我得到以下錯誤:

09-26 14:25:31.389 6427-7765/com.myapp.debug E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-7789 
    Process: com.myapp.debug, PID: 6427 
    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 

我試着把setTextSize一個runOnUiThread語句中,但我不能讓它在適配器內部工作。最終我只是想要這個工作。我覺得我的選擇是:

  1. 保持while循環在UI線程並以某種方式保護它(如何?)
  2. 移動setTextSize調用UI線程
  3. 其他的東西(如何?)?

感謝您的幫助!

UPDATE:根據Rustam的回答,我用wv.post寫入UI。然而,需要使用while循環意味着setTextSize必須在與while條件本身相同的線程中完成。我從評估TextView.getTextSize切換到Paint.getTextSize,因爲我可以設置Paint的文本大小而不影響UI,因此可以在分支線程內部進行設置。傑裏操縱,但它似乎工作。

private void shrinkText(final TextView wv, final String word) { 
    wv.setTextSize(defaultTextSize); 
    final Paint mPaint = new Paint(wv.getPaint()); 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
      while (wv.getWidth()>0 && mPaint.measureText(word) > wv.getWidth()) { 
       Logg.d("word too big. Shrink from " + mPaint.getTextSize()/density + " to " + (mPaint.getTextSize()/density-1.0f)); 
       mPaint.setTextSize(mPaint.getTextSize() - 1.0f); 
      } 
      if (wv.getWidth()>0 && wv.getPaint().measureText(word) > wv.getWidth()) { 
       wv.post(new Runnable() { 
        @Override 
        public void run() { 
         Logg.d(word + " final size=" + mPaint.getTextSize()/density); 
         wv.setTextSize(mPaint.getTextSize()/density); 
        } 
       }); 
      } 
     } 
    }).start(); 
} 

回答

0

嘗試更新這樣的:

private void shrinkText(final TextView wv, final String word) { 
    wv.setTextSize(defaultTextSize); 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
       while (wv.getWidth()>0 && wv.getPaint().measureText(word) > wv.getWidth()) { 
       Logg.d("word too big. Shrink from " + wv.getTextSize()/density + " to " + (wv.getTextSize()/density-1.0f)); 
       wv.post(new Runnable() { 
        public void run() { 
         wv.setTextSize(wv.getTextSize()/density - 1.0f); 
        } 
       }); 
     } 
    }).start(); 
} 
+0

只是去嘗試......如此看來,setTextSize需要在同一個線程while條件。它停止崩潰,但它也不會迭代 - 只是不斷重新運行,從14更改爲13,然後由於某種原因完全消失。 – Scott 2014-09-26 19:21:01

+0

那可能是計算問題.. – Rustam 2014-09-26 19:27:15

+0

我想我解決了這個問題。當然,我不能在while循環中使用wv.post方法,因爲while條件受setTextSize影響。我最終做的是在TextView中製作一個Paint對象的副本並對其進行評估 - 它不需要我寫入UI。然後,在完成while循環之後,我使用該Paint對象在Post方法中設置TextView的TextSize屬性。 – Scott 2014-09-27 00:54:41