Использование forceLayout(), requestLayout() и invalidate()

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

Когда они будут вызваны?

5 ответов

Решение

Чтобы лучше понять ответы, предоставленные Франсуа БУРЛЬЕ и Далвиком, я предлагаю вам взглянуть на эту удивительную диаграмму жизненного цикла представления от Арпит Матур:

invalidate()

призвание invalidate() делается, когда вы хотите запланировать перерисовку представления. Это приведет к onDraw вызывается в конце концов (скоро, но не сразу). Пример того, когда пользовательское представление будет вызывать его, - это когда свойство цвета текста или фона изменилось.

Вид будет перерисован, но размер не изменится.

requestLayout()

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

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

invalidate();
requestLayout();

Примером этого может быть изменение свойства текста у пользовательской метки. Ярлык изменит размер, и, следовательно, его необходимо переизмерить и перерисовать.

forceLayout()

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

Прочтите этот раздел вопросов и ответов для более подробного описания forceLayout(),

Дальнейшее обучение

Здесь вы можете найти ответ: http://developer.android.com/guide/topics/ui/how-android-draws.html

Для меня звонок в invalidate() только обновляет вид и вызов requestLayout() обновляет вид и вычисляет размер вида на экране.

invalidate() ---> onDraw() из потока пользовательского интерфейса

postInvalidate() ---> onDraw() из фонового потока

requestLayout() ---> onMeasure() а также onLayout()И НЕ обязательно onDraw()

  • ВАЖНО: вызов этого метода не влияет на дочерний объект вызываемого класса.

forceLayout() ---> onMeasure() а также onLayout() ТОЛЬКО ЕСЛИ прямой родитель позвонилrequestLayout().

Этот ответ не является правильным о forceLayout(),

Как вы можете видеть в коде forceLayout()он просто помечает представление как "нуждается в ретрансляции", но не планирует и не запускает это ретрансляцию. Ретрансляция не произойдет, пока в какой-то момент в будущем родительский элемент представления не будет выложен по какой-либо другой причине.

Существует также гораздо большая проблема при использовании forceLayout() а также requestLayout():

Допустим, вы позвонили forceLayout() на вид. Теперь при звонке requestLayout() на потомке этого представления, Android будет рекурсивно вызывать requestLayout() на предков этого потомка. Проблема в том, что он остановит рекурсию в представлении, на которое вы позвонили forceLayout(), Итак requestLayout() call никогда не достигнет корня представления и, следовательно, никогда не запланирует передачу макета. Целое поддерево иерархии представления ожидает макета и вызова requestLayout() ни при каком просмотре этого поддерева не вызовет раскладку. Только звоню requestLayout() любой вид за пределами этого поддерева разрушит заклинание.

Я бы рассмотрел реализацию forceLayout() (и как это влияет requestLayout() быть сломанным, и вы никогда не должны использовать эту функцию в вашем коде.

Вы используете invalidate () для представления, которое вы хотите перерисовать, оно вызовет onDraw (Canvas c) для вызова, а requestLayout() снова запустит весь рендеринг макета (фаза измерения и фаза позиционирования). Вы должны использовать его, если вы изменяете размер дочернего представления во время выполнения, но только в особых случаях, например, ограничения из родительского представления (под этим я подразумеваю, что высота или ширина родительского элемента равны WRAP_CONTENT и, таким образом, соответствуют измерению дочерних элементов, прежде чем они смогут снова их обернуть)

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