В этот ответ я написал
forceLayout()
Вызовите
forceLayout()
, если вы хотите только передать свое собственное представление контента, но не нужно запускать повторное измерение всего дерева представлений (все родительские представления). Если у вас есть пользовательскийViewGroup
, который не был изменяя свой собственный размер, но нуждаясь в том, чтобы детей, это будет подходящая ситуация дляforceLayout()
.В принципе, вызов
requestLayout()
приводит к вызовуparent.requestLayout()
, но вызовforceLayout()
не выполняется.
Насколько я помню, я написал свой ответ, прочитав документацию и source код. Однако я не использовал forceLayout
. Пользователь прокомментировал, что он не работал, как я описал.
Тестирование forceLayout
Я, наконец, обдумываю причину этого. Я создал простой проект с grandparent 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);
}
}