Я немного запутался о роли forceLayout()
, requestLayout()
и invalidate()
методов View
класса.
Когда они будут вызваны?
Я немного запутался о роли forceLayout()
, requestLayout()
и invalidate()
методов View
класса.
Когда они будут вызваны?
Чтобы лучше понять ответы Франсуа BOURLIEUX и Dalvik, я предлагаю вам взглянуть на эту удивительную диаграмму жизненного цикла представления от Arpit Mathur :
TextView
. Я подумал , что , может быть , они хотят , чтобы нарисоватьView
в последний раз , прежде чем они изменить его расположение связанных параметров, но это на самом деле не имеет никакого смысла , если мы думаем о тех вызовах, вызываемых в другом порядке (и они называютinvalidate()
сразу послеrequestLayout()
вTextView
также). Может быть, это заслуживает другого вопроса о StackOverflow :)?invalidate()
иrequestLayout()
) правильно. Цель этих методов - рассказать,View
что за недействительность (как вы ее назвали) произошла. Это не похоже наView
решение, по какому пути следовать после вызова одного из этих методов. Логика выбораView
-lifecycle-path - это выбор правильного метода для вызова самого себя. Если есть что-то, связанное с изменением размера -requestLayout()
следует вызвать, если есть только визуальное изменение без изменения размера - следует позвонитьinvalidate()
.View
каким-либо образом измените размер своего , например, вы получаете токLayoutParams
aView
и изменяете их, но НЕ вызываете ни один,requestLayout
ниsetLayoutParams
(который вызываетrequestLayout
внутри), то вы можете звонитьinvalidate()
столько, сколько хотите, иView
не будет проходить через процесс измерения верстки, поэтому не будет изменять его размер. Если вы не скажете,View
что его размер изменился (с помощьюrequestLayout
вызова метода), тогда онView
будет считать, что это не так,onMeasure
иonLayout
не будет вызываться.invalidate()
Вызов
invalidate()
выполняется, когда вы хотите запланировать перерисовку представления. Это приведет к тому,onDraw
что вызов будет в конце концов (скоро, но не сразу). Пример того, когда пользовательское представление будет вызывать его, - это когда свойство цвета текста или фона изменилось.Вид будет перерисован, но размер не изменится.
requestLayout()
Если что-то в вашем представлении изменится, что повлияет на размер, вам следует позвонить
requestLayout()
. Это сработает,onMeasure
иonLayout
не только для этого представления, но и до линии родительских представлений.Вызов
requestLayout()
будет не гарантировано приведет кonDraw
(вопреки тому , что предполагает диаграмма в общепринятом ответа), так что, как правило , в сочетании сinvalidate()
.Примером этого может быть изменение свойства текста у пользовательской метки. Ярлык изменит размер, и, следовательно, его необходимо переизмерить и перерисовать.
forceLayout()
Когда есть
requestLayout()
вызов, который вызывается в родительской группе представлений, нет необходимости пересматривать и ретранслировать его дочерние представления. Однако, если ребенок должен быть включен в переиздание и ретрансляцию, вы можете вызватьforceLayout()
ребенка.forceLayout()
работает только на ребенка, если это происходит в сочетании сrequestLayout()
на его непосредственном родителе. ВызовforceLayout()
сам по себе не будет иметь никакого эффекта, так как он не запускаетrequestLayout()
дерево представлений.Читать этот раздел вопросов и ответов для более подробного описания
forceLayout()
.Дальнейшее обучение
View
исходный кодисточник
requestLayout()
раньше,invalidate()
если хотите. Никто не делает макет или рисует сразу. Скорее, они устанавливают флаги, которые в конечном итоге приводят к ретрансляции и перерисовке.Здесь вы можете найти ответ: http://developer.android.com/guide/topics/ui/how-android-draws.html
Для меня вызов
invalidate()
только обновляет представление и вызов, чтобыrequestLayout()
обновить представление и вычислить размер представления на экране.источник
вы используете invalidate () для представления, которое вы хотите перерисовать, он вызовет его onDraw (Canvas c) для вызова, а requestLayout () заставит весь рендеринг макета (фаза измерения и фаза позиционирования) выполняться снова. Вы должны использовать его, если вы изменяете размер дочернего представления во время выполнения, но только в особых случаях, например, ограничения из родительского представления (под этим я подразумеваю, что высота или ширина родительского элемента равны WRAP_CONTENT и, таким образом, соответствуют измерению дочерних элементов, прежде чем они смогут снова их обернуть)
источник
Этот ответ не является правильным о
forceLayout()
.Как вы можете видеть в коде
forceLayout()
он просто помечает представление как «нуждается в ретрансляции», но он не планирует и не запускает это ретрансляцию. Ретрансляция не произойдет, пока в какой-то момент в будущем родительский элемент представления не будет выложен по какой-либо другой причине.Существует также гораздо большая проблема при использовании
forceLayout()
иrequestLayout()
:Допустим, вы позвонили
forceLayout()
на представление. Теперь при вызовеrequestLayout()
потомка этого представления Android будет рекурсивно вызыватьrequestLayout()
предков этого потомка. Проблема в том, что он остановит рекурсию в представлении, на которое вы звонилиforceLayout()
. Таким образом,requestLayout()
вызов никогда не достигнет корня представления и, следовательно, никогда не запланирует передачу макета. Целое поддерево иерархии представления ожидает макета, и вызовrequestLayout()
любого представления этого поддерева не вызовет макет. Только вызовrequestLayout()
любого вида за пределами этого поддерева разрушит заклинание.Я бы подумал, что реализация
forceLayout()
(и как она влияет,requestLayout()
будет нарушена, и вы никогда не должны использовать эту функцию в своем коде.источник
View
и сам разбираясь с проблемой и отлаживая ее.forceLayout()
API: он на самом деле не вызывает передачу макета, скорее он просто изменяет флаг, в котором наблюдаетсяonMeasure()
, ноonMeasure()
не будет вызываться, пока не будет вызванrequestLayout()
явныйView#measure()
. Это означает, что этоforceLayout()
должно быть в паре сrequestLayout()
. С другой стороны, зачем тогда выполнять,forceLayout()
если мне все еще нужно выполнятьrequestLayout()
?requestLayout()
делает все, чтоforceLayout()
делает.forceLayout
имеет смысл. Так что, в конце концов, он очень плохо назван и задокументирован.invalidate()
--->onDraw()
из пользовательского интерфейсаpostInvalidate()
--->onDraw()
из фоновой темыrequestLayout()
--->onMeasure()
иonLayout()
И НЕ ОБЯЗАТЕЛЬНОonDraw()
forceLayout()
--->onMeasure()
иonLayout()
ПРОСТО, ЕСЛИ позвонил прямой родительrequestLayout()
.источник