Использование 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()
,
Дальнейшее обучение
- Создание класса представления: добавление свойств и событий (полезные документы)
- Посмотреть документацию
View
исходный код
Здесь вы можете найти ответ: 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 и, таким образом, соответствуют измерению дочерних элементов, прежде чем они смогут снова их обернуть)