2014-09-26 76 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