Разметить вид после изменения размера

Я создаю сетку, которая отображает значения, которые меняются очень часто. Из-за этого я использую TextView, который автоматически изменяет размер при изменении его содержимого ( Auto Scale TextView Text для размещения в границах). Изменение размера происходит, но представление не размещается должным образом

макет после изменения размера

Дело в том, что когда я проверяю действие с HierarchyViewer, макет отображается так, как я хочу.

макет после иерархии просмотра

Я предполагаю, что HierarchyViewer вызывает requestLayout() или invalidate() для представления, но я пробовал это безуспешно. Этот код вызывается в основной деятельности без эффекта.

new Handler().postDelayed(new Runnable() {            
            @Override
            public void run() {
              getWindow().getDecorView().requestLayout();
              getWindow().getDecorView().invalidate();
            }
          }, 5000);

Я также пытался сделать вид недействительным после изменения размера.

TextView имеет гравитацию, установленную в центр, и если изменение размера не происходит, это выглядит хорошо.

Любая подсказка будет приветствоваться, заранее спасибо!

3 ответа

Решение

Я решил это, переопределив onLayout в одном из родительских объектов TextView и используя обработчик, созданный в конструкторе.

public class CellView extends LinearLayout{
   public CellView(Context context) {
     super(context);

     mHandler = new Handler();

     View.inflate(context, R.layout.cellview, this);
  }

 @Override
  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    if(changed){
      mHandler.post(new Runnable() {          
        @Override
        public void run() {
          requestLayout();
        }
      });
    }

   super.onLayout(changed, left, top, right, bottom);
  }

Я пытался вызвать requestLayout внутри onLayout TextView, хотя это не сработало, я не знаю почему. Это может быть связано с тем, что значение было обновлено через Observer, но прослушиватель onTextChanged должен происходить в потоке пользовательского интерфейса. Я надеюсь, что это служит кому-то еще

Путь requestLayout() работа заключается в том, что при вызове представления он будет планировать передачу макета для себя и всех своих дочерних элементов. Это желательно всякий раз, когда представление смещено или изменено в размере для изменения полей, отступов или содержимого.

Документация по методу getDecorView() не очень понятно, что именно это дает вам. Тем не менее, согласно документации на сайте:

Обратите внимание, что вызов этой функции в первый раз "блокирует" различные характеристики окна, как описано в setContentView(View, android.view.ViewGroup.LayoutParams).

Это оставляет меня верить, что есть что-то особенное в том, что getDecorView() извлекает. Что вы, вероятно, делаете, так это делаете макет представления постоянным, таким образом никогда не меняясь, когда requestLayout() проходить.

По-видимому, это правильный способ получить представление о корне всей вашей деятельности.

Однако, из соображений эффективности, я рекомендую звонить requestLayout() на самого низкого ребенка вы можете. Как я уже говорил ранее, он планирует передачу макета для представления, и это дети. Если вы передадите макет самого верхнего вида, вы по сути перестраиваете все, что включает в себя виды, которые остаются на месте.

Вам, вероятно, нужно запустить код таймера в потоке пользовательского интерфейса, используя runOnUiThread, как описано здесь.

Другие вопросы по тегам