Intereting Posts
Повторное действие андроида при нажатии и удержании кнопки Цвет текста действия с заставкой не меняется Как узнать, прокручивается ли ListView в верхней части позиции? Как добавить отслеживание / тайминги экрана в Firebase Analytics? Android, как отправить несколько контактов, подключен в один файл .vcf и отправляется по почте? Использование префикса пространства имен без андроида в дочерних элементах в макете Android добавит мое приложение в кнопку «Поделиться» в галерее Сколько действий против фрагментов? BroadcastReceiver или Messenger через обработчик Как диспетчеры задач убивают приложения? Как запросить информацию о приложении из магазина Google Play без аутентификации Плагин ADT не отображается в Eclipse Отображение огромной карты с хорошей производительностью на Android? Использование предварительно построенных статических библиотек для разработки Android NDK Запуск Activity from Preference Activity вызывает исключение отказа от разрешения

Почему requestLayout вызывается непосредственно после аннулирования

Я узнаю о пользовательских представлениях и хочу узнать об invalidate() и requestLayout() .

Пожалуйста, обратитесь к этому ответу и его диаграмме:

https://stackoverflow.com/a/25846243/4243687

invalidate() сообщает Android, что состояние представления изменилось и нуждается в повторном рисовании.

requestLayout() означает, что размер представления может измениться и его необходимо переоценить, а затем повторно нарисовать.

invalidate() будет вызывать dispatchDraw() , draw() и onDraw() следовательно, повторно отображает представление.

requestLayout() с другой стороны, делает почти все, от измерения до повторного рендеринга.

Почему так много примеров (даже исходный код TextView ) вызывает invalidate() а затем requestLayout() прямо на следующей строке?

Solutions Collecting From Web of "Почему requestLayout вызывается непосредственно после аннулирования"

invalidate() используется специально для перерисовки содержимого вашего представления. Перерисовать не происходит синхронно. Вместо этого он помещает область вашего представления как недопустимую, так что она будет перерисована во время следующего цикла рендеринга.

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

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

Если вы вернетесь и посмотрите места в коде для TextView где requestLayout() , это будет на методах, в которых будут затронуты границы представления. Например, setPadding() , setTypeface() , setCompoundDrawables() и т. Д.

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

Соответствующая выдержка из книги Expert Android, которая отвечает на вопрос:

Поскольку событие onClick вызвало изменение размеров, наше представление должно стать больше и занимать больше места. Как мы выражаем эту потребность Android, ну, мы запрашиваем Layout (). Этот метод поднимается по цепочке, отмечая каждого родителя представления, что его нужно переоценить. Когда конечный родитель получает этот запрос (корень представления), родительский график отправляет макет. Прохождение макета может или не может привести к onDraw, хотя в этом случае он должен. В качестве хорошей практики программирования мы также вызываем invalidate () для обеспечения фазы рисования.

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

Введите описание изображения здесь

Следовательно, не было бы необходимости называть их вместе, потому что это было бы излишним.

 invalidate(); requestLayout(); 

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

Мой источник (благодаря этому комментарию ) – Ромен Гай (который является инженером Android в Google):

Сама requestLayout () не приводит к ничьей, но некоторые взгляды могут реагировать на изменение макета, вызывая invalidate.

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

Android docs: создание класса View

 public boolean isShowText() { return mShowText; } public void setShowText(boolean showText) { mShowText = showText; invalidate(); requestLayout(); } 

Обратите внимание, что setShowText вызывает invalidate () и requestLayout (). Эти вызовы имеют решающее значение для обеспечения надежной работы представления. Вы должны аннулировать представление после любого изменения его свойств, которое может изменить его внешний вид, так что система знает, что его нужно перерисовать. Аналогично, вам нужно запросить новый макет, если изменяется свойство, которое может повлиять на размер или форму представления. Забывание этих вызовов метода может вызвать труднодоступные ошибки.