在我写的this answer
forceLayout()
如果您只想重新播放自己的视图,请致电
forceLayout()
内容,但不需要触发整个视图树的重新测量 (所有父视图)。如果您有自定义ViewGroup
则不是 改变自己的规模,但需要重新测量和重新布局 孩子,这将是一个适当的情况forceLayout()
。基本上,调用
requestLayout()
会导致调用parent.requestLayout()
,但是调用forceLayout()
没有。
我记得我通过阅读documentation和source code写了我的答案。但是,我没有使用forceLayout
。用户commented,它不像我描述的那样工作。
我终于开始研究这个原因了。我设置了一个简单项目,其中包含祖父母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
时,我什么也得不到。如果我一次调用它们,那么子视图的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
会产生更大的影响。
子
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);
}
}