Как forceLayout() работает в Android
В этом ответе я написал
forceLayout()
Вызов
forceLayout()
если вы хотите только ретранслировать содержимое вашего собственного представления, но не должны запускать повторное измерение всего дерева представлений (всех родительских представлений). Если у вас был обычайViewGroup
который не изменял свой собственный размер, но должен был переизмерить и ретранслировать своих детей, это была бы подходящая ситуация для вызоваforceLayout()
,В основном, звонит
requestLayout()
приводит к звонкуparent.requestLayout()
, но зоветforceLayout()
не делает.
Насколько я помню, я написал свой ответ, прочитав документацию и исходный код. Тем не менее, я не испытывал использование forceLayout
, Пользователь отметил, что он не работает, как я описал.
Тестирование forceLayout
Наконец-то я приступаю к исследованию причины этого. Я создал простой проект с бабушкой и дедушкой ViewGroup
, родитель ViewGroup
и ребенок View
, Я использовал настраиваемые представления для каждого из них, чтобы можно было просматривать операторы журнала в onMeasure
, onLayout
, а также onDraw
,
Когда макет впервые создается из XML, я получаю следующий журнал:
ViewGroupGrandparent onMeasure called
ViewGroupParent onMeasure called
MyChildView onMeasure called
ViewGroupGrandparent onMeasure called
ViewGroupParent onMeasure called
MyChildView onMeasure called
ViewGroupGrandparent onLayout called
ViewGroupParent onLayout called
MyChildView onLayout called
MyChildView onDraw called
forceLayout
Это выглядит как разумный вывод. Тем не менее, когда я впоследствии позвоню forceLayout
индивидуально ни по одному из просмотров я ничего не получаю. Если я позвоню им всем сразу, то детский взгляд onDraw
вызывается.
ребенок
childView.forceLayout();
// (no log output)
родитель
viewGroupParent.forceLayout();
// (no log output)
бабушка или дедушка
viewGroupGrandparent.forceLayout();
// (no log output)
все вместе
childView.forceLayout();
viewGroupParent.forceLayout();
viewGroupGrandparent.forceLayout();
// MyChildView onDraw called
requestLayout
С другой стороны, звонит requestLayout
имеет гораздо больший эффект.
ребенок
childView.requestLayout();
// ViewGroupGrandparent onMeasure called
// ViewGroupParent onMeasure called
// MyChildView onMeasure called
// ViewGroupGrandparent onLayout called
// ViewGroupParent onLayout called
// MyChildView onLayout called
// MyChildView onDraw called
родитель
viewGroupParent.requestLayout();
// ViewGroupGrandparent onMeasure called
// ViewGroupParent onMeasure called
// ViewGroupGrandparent onLayout called
// ViewGroupParent onLayout called
бабушка или дедушка
viewGroupGrandparent.requestLayout();
// ViewGroupGrandparent onMeasure called
// ViewGroupGrandparent onLayout called
Вопрос
Когда делает forceLayout
есть какой-либо эффект? Почему это не работает так, как предполагается в моих примерах выше?
Дополнительный код
Вот код, который я использовал для тестирования выше.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.forcelayout.MainActivity">
<com.example.forcelayout.ViewGroupGrandparent
android:id="@+id/view_group_grandparent"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.example.forcelayout.ViewGroupParent
android:id="@+id/view_group_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.example.forcelayout.MyChildView
android:id="@+id/child_view"
android:layout_width="100dp"
android:layout_height="100dp"/>
</com.example.forcelayout.ViewGroupParent>
</com.example.forcelayout.ViewGroupGrandparent>
<Button
android:text="Click me"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="buttonClick"/>
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void buttonClick(View view) {
Log.i("TAG", "buttonClick: ");
ViewGroupGrandparent viewGroupGrandparent = (ViewGroupGrandparent) findViewById(R.id.view_group_grandparent);
ViewGroupParent viewGroupParent = (ViewGroupParent) findViewById(R.id.view_group_parent);
MyChildView childView = (MyChildView) findViewById(R.id.child_view);
childView.forceLayout();
//viewGroupParent.forceLayout();
//viewGroupGrandparent.forceLayout();
//childView.requestLayout();
//viewGroupParent.requestLayout();
//viewGroupGrandparent.requestLayout();
}
}
ViewGroupGrandparent.java
public class ViewGroupGrandparent extends LinearLayout {
public ViewGroupGrandparent(Context context) {
super(context);
}
public ViewGroupGrandparent(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ViewGroupGrandparent(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i("TAG", "ViewGroupGrandparent onMeasure called");
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.i("TAG", "ViewGroupGrandparent onLayout called");
super.onLayout(changed, l, t, r, b);
}
@Override
protected void onDraw(Canvas canvas) {
Log.i("TAG", "ViewGroupGrandparent onDraw called");
super.onDraw(canvas);
}
}
ViewGroupParent.java
public class ViewGroupParent extends LinearLayout {
public ViewGroupParent(Context context) {
super(context);
}
public ViewGroupParent(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ViewGroupParent(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i("TAG", "ViewGroupParent onMeasure called");
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.i("TAG", "ViewGroupParent onLayout called");
super.onLayout(changed, l, t, r, b);
}
@Override
protected void onDraw(Canvas canvas) {
Log.i("TAG", "ViewGroupParent onDraw called");
super.onDraw(canvas);
}
}
MyChildView.java
public class MyChildView extends View {
public MyChildView(Context context) {
super(context);
}
public MyChildView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyChildView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i("TAG", "MyChildView onMeasure called");
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Log.i("TAG", "MyChildView onLayout called");
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
Log.i("TAG", "MyChildView onDraw called");
super.onDraw(canvas);
}
}
1 ответ
TL;DR Рассмотрим следующий код из TableLayout:
public void requestLayout() {
if (mInitialized) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).forceLayout();
}
}
super.requestLayout();
}
Здесь каждый дочерний элемент TableLayout будет помечен для измерения при последующем прохождении макета через вызов forceLayout()
, Аналогичная обработка произойдет, если requestLayout()
называется на каждого ребенка, но requestLayout()
пузыри вверх по иерархии зрения, поэтому requestLayout()
потомка TableLayout будет вызывать его родителя requestLayout()
, Это создаст бесконечный цикл с TableLayout и его дочерним элементом, вызывающим друг друга. forceLayout()
измерение силы без угрозы бесконечной рекурсии.
forceLayout()
не звонит requestLayout()
как указано, но очищает кэш представления и устанавливает пару флагов.
public void forceLayout() {
if (mMeasureCache != null) mMeasureCache.clear();
mPrivateFlags |= PFLAG_FORCE_LAYOUT;
mPrivateFlags |= PFLAG_INVALIDATED;
}
requestLayout()
очищает кеш и устанавливает такие же флаги как forceLayout()
но также может позвонить requestLayout()
на родителя.
public void requestLayout() {
if (mMeasureCache != null) mMeasureCache.clear();
...
mPrivateFlags |= PFLAG_FORCE_LAYOUT;
mPrivateFlags |= PFLAG_INVALIDATED;
if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
}
...
}
requestLayout()
должен пузыриться через всю иерархию.
Итак, что же forceLayout()
на самом деле делать? Чтобы исследовать этот вопрос, я взял предоставленное приложение и изменил его, чтобы отслеживать звонки onMeasure()
, onLayout()
а также onDraw()
для двух групп представлений (дед и родитель) и дочернего представления. Я добавила младшего ребенка к первому, чтобы сравнить, что происходит с ними двумя. Я также использовал отладчик для отслеживания вызовов measure()
а также requestLayout()
, Выходные данные были записаны в logcat, а из logcat была составлена электронная таблица, обобщающая операции. (Исходный код и ссылка на документацию в этом ответе каталогизированы в этом проекте GitHub.
Тестовое приложение вызывает forceLayout()
а также requestLayout()
для двух групп представлений и дочерних представлений во всех возможных комбинациях - всего 64. (Многие из этих комбинаций нереалистичны в реальном мире, но включены для полноты.) В таблице ниже приведены основные области для обсуждения. Полный лист можно найти в репозитории GitHub.
Раздел A - В этом разделе forceLayout()
называется на три вида. Как отметил Сурагч, на самом деле ничего не происходит, кроме onDraw()
называется когда forceLayout()
вызывается на все виды. Вот журнал для раздела A:
I / MainActivity: 1 *******************************************
I / MainActivity: 2 *******************************************
I / MainActivity: 3 *******************************************
I / MainActivity: 4 *******************************************
I / MainActivity: 5 *******************************************
I / MainActivity: 6 *******************************************
I / MainActivity: 7 *******************************************
I / MyChildView: вызывается onDraw (1)
"1 ****..." соответствует строке в электронной таблице. Строки типа "I/MyChildView: onDraw named (1)" идентифицируют представление ("MyChildView"), метод представления ("onDraw") и "(x)" будут "(1)" для первого дочернего представления ". (2) "для второго дочернего представления и" (null) "для других не дочерних представлений.
Это неожиданный результат, учитывая имя метода: forceLayout()
,
Раздел B - В строке 8, requestLayout()
вызывается на дочернем виде, и результаты ожидаются: мера, макет и проход чертежа принимаются на всех видах. Строка 9 добавляет вызов forceLayout()
ребенку, но результаты одинаковы. Вот журнал для раздела B:
/ MainActivity: 8 *******************************************
I / requestLayout: MyChildView (1)
I / requestLayout: MyChildView isLayoutRequested = false (1)
I / requestLayout: ViewGroupParent (null)
I / requestLayout: ViewGroupParent isLayoutRequested = false (null)
I / requestLayout: ViewGroupGrandparent (null)
I / requestLayout: ViewGroupGrandparent isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: ContentFrameLayout (null)
I / requestLayout: ContentFrameLayout isLayoutRequested = false (null)
I / requestLayout: ActionBarOverlayLayout (null)
I / requestLayout: ActionBarOverlayLayout isLayoutRequested = false (null)
I / requestLayout: FrameLayout (null)
I / requestLayout: FrameLayout isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: DecorView (null)
I / requestLayout: DecorView isLayoutRequested = false (null)
I / measure: ViewGroupGrandparent (null)
I / ViewGroupGrandparent: onMeasure вызывается
I / measure: ViewGroupParent (null)
I / ViewGroupParent: вызывается onMeasure
Я / мера: MyChildView (1)
I / MyChildView: onMeasure вызывается (1)
Я / мера: MyChildView (2)
I / ViewGroupGrandparent: onLayout вызывается
I/ViewGroupParent: onLayout вызывается
I/MyChildView: onLayout вызывается (1)
I / MyChildView: вызывается onDraw (1)
I / MainActivity: 9 *******************************************
I / requestLayout: MyChildView (1)
I / requestLayout: MyChildView isLayoutRequested = false (1)
I / requestLayout: ViewGroupParent (null)
I / requestLayout: ViewGroupParent isLayoutRequested = false (null)
I / requestLayout: ViewGroupGrandparent (null)
I / requestLayout: ViewGroupGrandparent isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: ContentFrameLayout (null)
I / requestLayout: ContentFrameLayout isLayoutRequested = false (null)
I / requestLayout: ActionBarOverlayLayout (null)
I / requestLayout: ActionBarOverlayLayout isLayoutRequested = false (null)
I / requestLayout: FrameLayout (null)
I / requestLayout: FrameLayout isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: DecorView (null)
I / requestLayout: DecorView isLayoutRequested = false (null)
I / measure: ViewGroupGrandparent (null)
I / ViewGroupGrandparent: onMeasure вызывается
I / measure: ViewGroupParent (null)
I / ViewGroupParent: вызывается onMeasure
Я / мера: MyChildView (1)
I / MyChildView: onMeasure вызывается (1)
Я / мера: MyChildView (2)
I / ViewGroupGrandparent: onLayout вызывается
I/ViewGroupParent: onLayout вызывается
I/MyChildView: onLayout вызывается (1)
I / MyChildView: вызывается onDraw (1)
Раздел C - Здесь все становится интереснее. Для строк 10 и 11 requestLayout()
вызывается на вид ребенка и forceLayout()
вызывается в родительском представлении ребенка. В результате последующие этапы измерения / разметки / прорисовки, которые мы видели в разделе B, не выполняются. Я считаю, что именно поэтому Fluidsonic сказал, что forceLayout()
сломано. См. /questions/35703792/ispolzovanie-forcelayout-requestlayout-i-invalidate/35703795#35703795.
На самом деле, дочерний вид рассматривает вызов requestLayout()
на родительском, но обнаруживает, что макет уже был запрошен на родительском. (mParent != null && !mParent.isLayoutRequested()
). Вот ссылка на код для isLayoutRequested()
,
public boolean isLayoutRequested() {
return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
}
Помни что forceLayout()
установить PFLAG_FORCE_LAYOUT
флаг. Вот почему requestLayout()
цепь останавливается у родителя. Это может быть проблемой или просто неправильным использованием forceLayout()
,
Продолжая с остальной частью раздела C, самое большее, что мы можем "заставить", это призыв к ребенку. onDraw()
,
Вот журнал для раздела C:
I / MainActivity: 10 *******************************************
I / requestLayout: MyChildView (1)
I / requestLayout: MyChildView isLayoutRequested = true (1)
I / MainActivity: 11 *******************************************
I / requestLayout: MyChildView (1)
I / requestLayout: MyChildView isLayoutRequested = true (1)
I / MainActivity: 12 *******************************************
I / requestLayout: MyChildView (1)
I / requestLayout: MyChildView isLayoutRequested = false (1)
I / requestLayout: ViewGroupParent (null)
I / requestLayout: ViewGroupParent isLayoutRequested = true (null)
I / MyChildView: вызывается onDraw (1)
I / MainActivity: 13 *******************************************
I / requestLayout: MyChildView (1)
I / requestLayout: MyChildView isLayoutRequested = false (1)
I / requestLayout: ViewGroupParent (null)
I / requestLayout: ViewGroupParent isLayoutRequested = true (null)
I / MyChildView: вызывается onDraw (1)
I / MainActivity: 14 *******************************************
I / requestLayout: MyChildView (1)
I / requestLayout: MyChildView isLayoutRequested = true (1)
I / MyChildView: вызывается onDraw (1)
I / MainActivity: 15 *******************************************
I / requestLayout: MyChildView (1)
I / requestLayout: MyChildView isLayoutRequested = true (1)
I / MyChildView: вызывается onDraw (1)
Раздел D - Этот раздел может содержать секрет forceLayout()
, В строке 16 звоните requestLayout()
на родительском элементе получается проход меры / макета для родителя и деда, но не для ребенка. Если звонок в forceLayout()
сделано на ребенка, то ребенок включен. На самом деле, звонок сделан на ребенка onMeasure()
в то время как звонок не сделан к его родному брату onMeasure()
, Это связано с призывом к forceLayout()
на ребенка. Итак, похоже, что здесь forceLayout()
используется, чтобы заставить систему измерить ребенка, который обычно не измеряется. Я отмечу, что это, кажется, происходит только тогда, когда forceLayout()
вызывается по прямому потомку целевого представления requestLayout()
,
Один такой пример этого типа обработки находится в TableLayout. в requestLayout()
переопределить в TableLayout, forceLayout()
называется на каждого ребенка. Это позволит избежать звонка requestLayout()
на каждого ребенка и связанные с этим накладные расходы (хотя, вероятно, небольшие). Это также позволит избежать катастрофической рекурсии, так как ребенок requestLayout()
может позвонить родителям requestLayout()
это назовет ребенка... вы поняли. Вот код из TableLayout:
public void requestLayout() {
if (mInitialized) {
int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).forceLayout();
}
}
super.requestLayout();
}
В ListView.java необходимо повторно измерить ребенка перед повторным использованием. См. Код здесь. forceLayout()
работает здесь, чтобы переоценить ребенка.
// Since this view was measured directly aginst the parent measure
// spec, we must measure it again before reuse.
child.forceLayout();
Вот журнал для раздела D:
I / MainActivity: 16 *******************************************
I / requestLayout: ViewGroupParent (null)
I / requestLayout: ViewGroupParent isLayoutRequested = false (null)
I / requestLayout: ViewGroupGrandparent (null)
I / requestLayout: ViewGroupGrandparent isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: ContentFrameLayout (null)
I / requestLayout: ContentFrameLayout isLayoutRequested = false (null)
I / requestLayout: ActionBarOverlayLayout (null)
I / requestLayout: ActionBarOverlayLayout isLayoutRequested = false (null)
I / requestLayout: FrameLayout (null)
I / requestLayout: FrameLayout isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: DecorView (null)
I / requestLayout: DecorView isLayoutRequested = false (null)
I / measure: ViewGroupGrandparent (null)
I / ViewGroupGrandparent: onMeasure вызывается
I / measure: ViewGroupParent (null)
I / ViewGroupParent: вызывается onMeasure
Я / мера: MyChildView (1)
Я / мера: MyChildView (2)
I / ViewGroupGrandparent: onLayout вызывается
I/ViewGroupParent: onLayout вызывается
I / MainActivity: 17 *******************************************
I / requestLayout: ViewGroupParent (null)
I / requestLayout: ViewGroupParent isLayoutRequested = false (null)
I / requestLayout: ViewGroupGrandparent (null)
I / requestLayout: ViewGroupGrandparent isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: ContentFrameLayout (null)
I / requestLayout: ContentFrameLayout isLayoutRequested = false (null)
I / requestLayout: ActionBarOverlayLayout (null)
I / requestLayout: ActionBarOverlayLayout isLayoutRequested = false (null)
I / requestLayout: FrameLayout (null)
I / requestLayout: FrameLayout isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: DecorView (null)
I / requestLayout: DecorView isLayoutRequested = false (null)
I / measure: ViewGroupGrandparent (null)
I / ViewGroupGrandparent: onMeasure вызывается
I / measure: ViewGroupParent (null)
I / ViewGroupParent: вызывается onMeasure
Я / мера: MyChildView (1)
I / MyChildView: onMeasure вызывается (1)
Я / мера: MyChildView (2)
I / ViewGroupGrandparent: onLayout вызывается
I/ViewGroupParent: onLayout вызывается
I/MyChildView: onLayout вызывается (1)
I / MyChildView: вызывается onDraw (1)
Раздел E - Этот раздел дополнительно демонстрирует, что только прямые потомки целевого представления вызова requestLayout()
Кажется, участвует в триггере проходов. Строки 34 и 35, кажется, указывают на то, что вложенные представления могут быть цепными.
Вот журнал для раздела E:
I / MainActivity: 32 *******************************************
I / requestLayout: ViewGroupGrandparent (null)
I / requestLayout: ViewGroupGrandparent isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: ContentFrameLayout (null)
I / requestLayout: ContentFrameLayout isLayoutRequested = false (null)
I / requestLayout: ActionBarOverlayLayout (null)
I / requestLayout: ActionBarOverlayLayout isLayoutRequested = false (null)
I / requestLayout: FrameLayout (null)
I / requestLayout: FrameLayout isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: DecorView (null)
I / requestLayout: DecorView isLayoutRequested = false (null)
I / measure: ViewGroupGrandparent (null)
I / ViewGroupGrandparent: onMeasure вызывается
I / measure: ViewGroupParent (null)
I / ViewGroupGrandparent: onLayout вызывается
I / MainActivity: 33 *******************************************
I / requestLayout: ViewGroupGrandparent (null)
I / requestLayout: ViewGroupGrandparent isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: ContentFrameLayout (null)
I / requestLayout: ContentFrameLayout isLayoutRequested = false (null)
I / requestLayout: ActionBarOverlayLayout (null)
I / requestLayout: ActionBarOverlayLayout isLayoutRequested = false (null)
I / requestLayout: FrameLayout (null)
I / requestLayout: FrameLayout isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: DecorView (null)
I / requestLayout: DecorView isLayoutRequested = false (null)
I / measure: ViewGroupGrandparent (null)
I / ViewGroupGrandparent: onMeasure вызывается
I / measure: ViewGroupParent (null)
I / ViewGroupGrandparent: onLayout вызывается
I / MainActivity: 34 *******************************************
I / requestLayout: ViewGroupGrandparent (null)
I / requestLayout: ViewGroupGrandparent isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: ContentFrameLayout (null)
I / requestLayout: ContentFrameLayout isLayoutRequested = false (null)
I / requestLayout: ActionBarOverlayLayout (null)
I / requestLayout: ActionBarOverlayLayout isLayoutRequested = false (null)
I / requestLayout: FrameLayout (null)
I / requestLayout: FrameLayout isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: DecorView (null)
I / requestLayout: DecorView isLayoutRequested = false (null)
I / measure: ViewGroupGrandparent (null)
I / ViewGroupGrandparent: onMeasure вызывается
I / measure: ViewGroupParent (null)
I / ViewGroupParent: вызывается onMeasure
Я / мера: MyChildView (1)
Я / мера: MyChildView (2)
I / ViewGroupGrandparent: onLayout вызывается
I/ViewGroupParent: onLayout вызывается
I / MainActivity: 35 *******************************************
I / requestLayout: ViewGroupGrandparent (null)
I / requestLayout: ViewGroupGrandparent isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: ContentFrameLayout (null)
I / requestLayout: ContentFrameLayout isLayoutRequested = false (null)
I / requestLayout: ActionBarOverlayLayout (null)
I / requestLayout: ActionBarOverlayLayout isLayoutRequested = false (null)
I / requestLayout: FrameLayout (null)
I / requestLayout: FrameLayout isLayoutRequested = false (null)
I / requestLayout: LinearLayout (null)
I / requestLayout: LinearLayout isLayoutRequested = false (null)
I / requestLayout: DecorView (null)
I / requestLayout: DecorView isLayoutRequested = false (null)
I / measure: ViewGroupGrandparent (null)
I / ViewGroupGrandparent: onMeasure вызывается
I / measure: ViewGroupParent (null)
I / ViewGroupParent: вызывается onMeasure
Я / мера: MyChildView (1)
I / MyChildView: onMeasure вызывается (1)
Я / мера: MyChildView (2)
I / ViewGroupGrandparent: onLayout вызывается
I/ViewGroupParent: onLayout вызывается
I/MyChildView: onLayout вызывается (1)
I / MyChildView: вызывается onDraw (1)
Так что это мой вынос на forceLayout()
: Используйте его, когда есть дети, которые необходимо повторно измерить, например, в TableLayout, и вы не хотите звонить requestLayout()
на каждого ребенка - forceLayout()
Это легкий вес и позволит избежать рекурсии. (См. Примечания в разделе С.) forceLayout()
может также использоваться для принудительного переопределения конкретных прямых детей, когда это необходимо, когда они обычно не измеряются. forceLayout()
не работает в одиночку и должен быть в паре с соответствующими вызовами requestLayout()