Я использую GridView для отображения списка слов в таблице из четырех столбцов. Метод getView моего пользовательского адаптера проверяет ширину слова и сжимает его, если он не подходит. Он делает это с помощью рекурсивной проверки, которая сохраняет масштабирование текста до до.Android: обновление пользовательского интерфейса от адаптера внутри цикла while
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();
}
Так как я использую в то время цикл, я использую новую нить для защиты от НР в маловероятном случае, бесконечный цикл. Вот что странно: иногда отлично работает. А потом иногда я получаю следующее сообщение об ошибке:
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, но я не могу заставить его работать внутри адаптера. В конечном итоге я просто хочу, чтобы это сработало. Я думаю, что мои варианты:
- Держите время цикла в потоке пользовательского интерфейса и каким-то образом защитить его (как?)
- Перемещение setTextSize вызов в потоке пользовательского интерфейса
- Что-то еще (как?)?
Благодарим за помощь!
ОБНОВЛЕНИЕ: на основании ответа Рустама я использовал wv.post для записи в пользовательский интерфейс. Однако необходимость использования цикла while означала, что setTextSize должен выполняться в том же потоке, что и условие while. Я переключился с оценки TextView.getTextSize на Paint.getTextSize, так как я мог установить размер текста Paint без влияния на пользовательский интерфейс и, следовательно, в потоке ответвления. Джерри сфальсифицирован, но, похоже, он работает.
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();
}
Просто пробовал ... Кажется, что setTextSize должен быть в том же потоке, что и условия в то время. Он прекратил рушиться, но он также не выполняет итерацию - просто продолжает переизбираться с 14 на 13, а затем по какой-то причине вообще исчезает с экрана. – Scott
это может быть проблемой расчета. – Rustam
Я думаю, что я решил проблему. Конечно, я не могу использовать метод wv.post внутри цикла while, так как условие while влияет на setTextSize. То, что я закончил, это сделать копию объекта Paint в TextView и оценить это - мне не потребовалось писать в пользовательский интерфейс. Затем после завершения цикла while я использовал этот объект Paint, чтобы установить свойство TextSize TextView внутри метода post. – Scott