如何在Android中使用forceLayout() [英] How does forceLayout() work in Android

查看:137
本文介绍了如何在Android中使用forceLayout()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写的答案

forceLayout()

如果只想中继自己视图的,请致电forceLayout() 内容,但无需触发整个视图树的重新评估 (所有父视图).如果您有一个自定义ViewGroup,那不是 更改自己的尺寸,但需要重新测量并重新发布 孩子们,这是一个合适的情况 forceLayout().

forceLayout()

Call forceLayout() if you only want to relayout your own view's content, but don't need to trigger remeasuring of the entire view tree (all the parent views). If you had a custom ViewGroup that wasn't changing its own size but needed to remeasure and relayout its children, this would be an appropriate situation to call forceLayout().

基本上,调用requestLayout()会导致对 parent.requestLayout(),但不会调用forceLayout().

Basically, calling requestLayout() results in a call to parent.requestLayout(), but calling forceLayout() doesn't.

回想起我通过阅读文档评论,它没有按照我的描述进行操作.

As I recall I wrote my answer by reading the documentation and source code. However, I didn't experience using forceLayout. A user commented that it was not working as I described.

我终于可以开始研究造成这种情况的原因了.我用祖父母ViewGroup,父母ViewGroup和孩子View设置了一个简单的项目.我为每个视图都使用了自定义视图,以便可以查看onMeasureonLayoutonDraw中的日志语句.

I am finally getting around to researching the cause for this. I set up a simple project with a grandparent ViewGroup, a parent ViewGroup, and a child View. I used custom views for each of them so that I could watch the log statements in onMeasure, onLayout, and onDraw.

第一次从xml创建布局时,我得到以下日志:

When the layout is first created from xml I get the following log:

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会被调用.

forceLayout

This looks like reasonable output. However, when I subsequently call forceLayout individually on any of the views I get nothing. If I call them all at once, then the child view's onDraw gets called.

孩子

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具有更大的效果.

requestLayout

On the other hand, calling requestLayout has a much bigger effect.

孩子

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何时生效?为什么它似乎不像上面的示例那样起作用?

Question

When does forceLayout have any effect? Why doesn't it seem to work as it is supposed to in my examples above?

这是我用来进行上述测试的代码.

Here is the code I used to make the tests above.

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);
    }
}

推荐答案

TL; DR考虑TableLayout中的以下代码:

TL;DR Consider the following code from 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()在视图层次结构中冒泡,因此TableLayout的子级requestLayout()将调用其父级的requestLayout().这将使用TableLayout及其子对象相互调用来建立一个无限循环. forceLayout()强制进行测量,而没有无限递归的威胁.

Here each child of the TableLayout will be flagged to be measured on a future layout pass through a call to forceLayout(). Similar processing will occur if requestLayout() is called on each child, but requestLayout() bubbles up through the view hierachy, so the requestLayout() of a child of TableLayout will call its parent's requestLayout(). This will set up an infinite loop with TableLayout and its child calling one another. forceLayout() forces measurement without the threat of infinite recursion.

forceLayout() 不会像上面所说的那样在其父级上调用requestLayout(),但是会清除视图的缓存并设置几个标志.

forceLayout() does not call requestLayout() on its parent as stated but clears the view's cache and sets a couple of flags.

public void forceLayout() {
    if (mMeasureCache != null) mMeasureCache.clear();
    mPrivateFlags |= PFLAG_FORCE_LAYOUT;
    mPrivateFlags |= PFLAG_INVALIDATED;
}

requestLayout() 清除缓存并将这些相同的标志设置为forceLayout(),但也可能在父级上调用requestLayout().

requestLayout() clears the cache and sets these same flags as forceLayout() but also might call requestLayout() on the parent.

public void requestLayout() {
    if (mMeasureCache != null) mMeasureCache.clear();
    ...
    mPrivateFlags |= PFLAG_FORCE_LAYOUT;
    mPrivateFlags |= PFLAG_INVALIDATED;

    if (mParent != null && !mParent.isLayoutRequested()) {
        mParent.requestLayout();
    }
    ...
}

requestLayout()应该在整个层次结构中冒泡.

requestLayout() should bubble up through the entire hierarchy.

那么,forceLayout()实际上是做什么的?为了研究这个问题,我使用提供的应用程序并对它进行了修改,以跟踪对两个视图组(祖父母和父视图)和子视图的onMeasure()onLayout()onDraw()的调用.我在第一个孩子中添加了一个同胞孩子,以比较两个孩子的情况.我还使用调试器来跟踪对measure()requestLayout()的调用.在logcat中捕获了输出,并从logcat中生成了一个汇总操作的电子表格. (此答案中的源代码和文档参考位于此GitHub项目.

So, what does forceLayout() actually do? To research this question, I took the provided app and modified it to trace calls to onMeasure(), onLayout() and onDraw() for the two view groups (Grandparent and Parent) and the child view. I added a sibling child to the first to compare what happens to the two of them. I also used the debugger to trace calls to measure() and requestLayout(). Output was captured in logcat and from logcat a spreadsheet was produced summarizing the operations. (Source code and documentation reference in this answer is cataloged at this GitHub project.

测试应用程序以所有可能的组合(总共64个)调用两个视图组和子视图的forceLayout()requestLayout(). (这些组合中的许多组合在现实世界中并不现实,但为了完整起见而包括在内.)以下电子表格总结了讨论的关键领域.完整的工作表可以在GitHub存储库中找到.

The test app calls forceLayout() and requestLayout() for the two view groups and child view in all possible combinations - 64 in all. (Many of these combinations are not realistic in the real world, but are included for completeness.) The spreadsheet below summarizes key areas for discussion. The full sheet can be found at the GitHub repository.

A部分-在此部分中,在三个视图上调用forceLayout().正如Suragch指出的那样,当在所有视图上调用forceLayout()时,除了调用onDraw()之外,什么都没有发生.这是A部分的日志:

Section A - In this section, forceLayout() is called on the three views. As Suragch noted, nothing really happens other than onDraw() is called when forceLayout() is invoked on all the views. Here is the log for section 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)

I/MainActivity: 1*******************************************
I/MainActivity: 2*******************************************
I/MainActivity: 3*******************************************
I/MainActivity: 4*******************************************
I/MainActivity: 5*******************************************
I/MainActivity: 6*******************************************
I/MainActivity: 7*******************************************
I/MyChildView: onDraw called (1)

"1 **** ..."对应于电子表格中的行.像"I/MyChildView:称为(1)的onDraw"这样的行标识了视图("MyChildView"),对于第一个子视图,视图方法("onDraw")和(x)"将为(1)", (2)为第二个子视图,(null)"为其他非子视图.

"1****..." corresponds to the line in the spreadsheet. Lines like "I/MyChildView: onDraw called (1)" identifies the view ("MyChildView"), the view method ("onDraw") and "(x)" will be "(1)" for the first child view, "(2)" for the second child view and "(null)" for other non-child views.

在方法名称为forceLayout()的情况下,这是意外结果.

This is an unexpected result given the name of the method: forceLayout().

B部分-在第8行上,在子视图上调用了requestLayout(),并且期望得到结果:在所有视图上都执行了度量,布局和绘图传递.第9行向子级添加对forceLayout()的调用,但结果相同.这是B部分的日志:

Section B - On line 8, requestLayout() is called on the child view and the results are expected: a measure, layout and drawing pass are taken on all the views. Line 9 adds a call to forceLayout() to the child, but the results are the same. Here is the log for section B:

/MainActivity:8 ***********************************************
I/requestLayout:MyChildView(1)
I/requestLayout:MyChildView isLayoutRequested = false(1)
I/requestLayout:ViewGroupParent(空)
I/requestLayout:ViewGroupParent isLayoutRequested = false(空)
I/requestLayout:ViewGroupGrandparent(空)
I/requestLayout:ViewGroupGrandparent isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:ContentFrameLayout(空)
I/requestLayout:ContentFrameLayout isLayoutRequested = false(空)
I/requestLayout:ActionBarOverlayLayout(空)
I/requestLayout:ActionBarOverlayLayout isLayoutRequested = false(空)
I/requestLayout:FrameLayout(空)
I/requestLayout:FrameLayout isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:DecorView(空)
I/requestLayout:DecorView isLayoutRequested = false(空)
I/measure:ViewGroupGrandparent(空)
I/ViewGroupGrandparent:称为onMeasure的
I/措施:ViewGroupParent(空)
I/ViewGroupParent:onMeasure被称为
I/measure:MyChildView(1)
I/MyChildView:onMeasure称为(1)
I/measure: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(空)
I/requestLayout:ViewGroupParent isLayoutRequested = false(空)
I/requestLayout:ViewGroupGrandparent(空)
I/requestLayout:ViewGroupGrandparent isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:ContentFrameLayout(空)
I/requestLayout:ContentFrameLayout isLayoutRequested = false(空)
I/requestLayout:ActionBarOverlayLayout(空)
I/requestLayout:ActionBarOverlayLayout isLayoutRequested = false(空)
I/requestLayout:FrameLayout(空)
I/requestLayout:FrameLayout isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:DecorView(空)
I/requestLayout:DecorView isLayoutRequested = false(空)
I/measure:ViewGroupGrandparent(空)
I/ViewGroupGrandparent:称为onMeasure的
I/措施:ViewGroupParent(空)
I/ViewGroupParent:onMeasure被称为
I/measure:MyChildView(1)
I/MyChildView:onMeasure称为(1)
I/measure:MyChildView(2)
I/ViewGroupGrandparent:onLayout被称为
I/ViewGroupParent:onLayout被称为
I/MyChildView:onLayout称为(1)
I/MyChildView:onDraw称为(1)

/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 called
I/measure: ViewGroupParent (null)
I/ViewGroupParent: onMeasure called
I/measure: MyChildView (1)
I/MyChildView: onMeasure called (1)
I/measure: MyChildView (2)
I/ViewGroupGrandparent: onLayout called
I/ViewGroupParent: onLayout called
I/MyChildView: onLayout called (1)
I/MyChildView: onDraw called (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 called
I/measure: ViewGroupParent (null)
I/ViewGroupParent: onMeasure called
I/measure: MyChildView (1)
I/MyChildView: onMeasure called (1)
I/measure: MyChildView (2)
I/ViewGroupGrandparent: onLayout called
I/ViewGroupParent: onLayout called
I/MyChildView: onLayout called (1)
I/MyChildView: onDraw called (1)

C部分-这是有趣的地方.对于第10行和第11行,在子视图上调用requestLayout(),在子视图上调用forceLayout().结果是,我们在B节中看到的后续测量/布局/绘制过程不会发生.我相信这就是为什么Fluidsonic指出forceLayout()被破坏的原因.参见 https://stackoverflow.com/a/44781500/6287910 .

Section C - Here is where things get interesting. For lines 10 and 11, requestLayout() is called on the child view and forceLayout() is called on the child's parent view. The result is that the subsequent measure/layout/draw passes that we saw in section B do not happen. I believe that this is why fluidsonic said that forceLayout() is broken. See https://stackoverflow.com/a/44781500/6287910.

实际上,子视图考虑在父视图上调用requestLayout(),但是发现已经在父视图上请求了布局. (mParent != null && !mParent.isLayoutRequested()).这是链接isLayoutRequested()的代码.

In fact, the child view considers calling requestLayout() on the parent but finds that a layout has already been requested on the parent. (mParent != null && !mParent.isLayoutRequested()). Here is a link to the code for isLayoutRequested().

public boolean isLayoutRequested() {
    return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
}

请记住,forceLayout()设置了PFLAG_FORCE_LAYOUT标志.这就是requestLayout()链在父级停止的原因.这可能是一个问题,或者只是误用了forceLayout().

Remember that forceLayout() set the PFLAG_FORCE_LAYOUT flag. This is why the requestLayout() chain stops at the parent. This could be an issue or just a misuse of forceLayout().

继续进行C节的其余部分,我们最大可以强迫"使用的是呼叫孩子的onDraw().

Continuing on with the rest of section C, the most we can "force" is a call to the child's 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(空)
I/requestLayout:ViewGroupParent isLayoutRequested = true(空)
I/MyChildView:onDraw称为(1)
I/MainActivity:13 ***********************************************
I/requestLayout:MyChildView(1)
I/requestLayout:MyChildView isLayoutRequested = false(1)
I/requestLayout:ViewGroupParent(空)
I/requestLayout:ViewGroupParent isLayoutRequested = true(空)
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)

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 called (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 called (1)
I/MainActivity: 14*******************************************
I/requestLayout: MyChildView (1)
I/requestLayout: MyChildView isLayoutRequested=true (1)
I/MyChildView: onDraw called (1)
I/MainActivity: 15*******************************************
I/requestLayout: MyChildView (1)
I/requestLayout: MyChildView isLayoutRequested=true (1)
I/MyChildView: onDraw called (1)

D部分-此部分可能会将秘密保存在forceLayout()中.在第16行上,对父级上的requestLayout()的调用会导致对父级和祖父母而不是子级进行度量/布局传递.如果在子项上调用了forceLayout(),则该子项将包括在内.实际上,对孩子的onMeasure()进行了呼叫,而对同级的onMeasure()没有进行呼叫.这是由于在子级上调用了forceLayout()所致.因此,似乎在这里forceLayout()被用来强制框架测量通常不会被测量的孩子.我会注意到,这似乎仅在requestLayout()的目标视图的_direct后代上调用forceLayout()时才会发生.

Section D - This section may hold the secret to forceLayout(). On line 16, a call to requestLayout() on the parent results in a measure/layout pass for the parent and the grandparent but not the child. If a call to forceLayout() is made on the child, then the child is included. In fact, a call is made to the child's onMeasure() while a call is not made to its sibling's onMeasure(). This is due to the call to forceLayout() on the child. So, it seems, that here forceLayout() is being used to force the framework to measure a child that would not ordinarily be measured. I will note that this only seems to happen when forceLayout() is called on a _direct descendent of the target view of requestLayout().

此类此类处理的示例在TableLayout中.在TableLayout的requestLayout()替代中,在每个子级上调用forceLayout().这样可以避免在每个子代上调用requestLayout()以及随之而来的相关开销(尽管可能很小).这也将避免灾难性的递归,因为孩子的requestLayout()可能会调用父级的requestLayout(),而父级的requestLayout()会调用孩子的requestLayout().这是来自TableLayout的代码:

One such example of this type of processing is in TableLayout. In the requestLayout() override in TableLayout, forceLayout() is called on each child. This will avoid calling requestLayout() on each child and the associated overhead that would entail (although probably small). It will also avoid disastrous recursion since the child's requestLayout() may call the parent's requestLayout() that will call the child's...you get the idea. Here is the code from TableLayout:

public void requestLayout() {
        if (mInitialized) {
            int count = getChildCount();
            for (int i = 0; i < count; i++) {
                getChildAt(i).forceLayout();
            }
        }

        super.requestLayout();
}

在ListView.java中,需要在重新使用之前重新测量子级.请参见代码

In ListView.java, there is a need to remeasure a child before reuse See the code here. forceLayout() works here to get the child remeasured.

// 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(空)
I/requestLayout:ViewGroupParent isLayoutRequested = false(空)
I/requestLayout:ViewGroupGrandparent(空)
I/requestLayout:ViewGroupGrandparent isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:ContentFrameLayout(空)
I/requestLayout:ContentFrameLayout isLayoutRequested = false(空)
I/requestLayout:ActionBarOverlayLayout(空)
I/requestLayout:ActionBarOverlayLayout isLayoutRequested = false(空)
I/requestLayout:FrameLayout(空)
I/requestLayout:FrameLayout isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:DecorView(空)
I/requestLayout:DecorView isLayoutRequested = false(空)
I/measure:ViewGroupGrandparent(空)
I/ViewGroupGrandparent:称为onMeasure的
I/措施:ViewGroupParent(空)
I/ViewGroupParent:onMeasure被称为
I/measure:MyChildView(1)
I/measure:MyChildView(2)
I/ViewGroupGrandparent:onLayout被称为
I/ViewGroupParent:onLayout被称为
I/MainActivity:17 ***********************************************
I/requestLayout:ViewGroupParent(空)
I/requestLayout:ViewGroupParent isLayoutRequested = false(空)
I/requestLayout:ViewGroupGrandparent(空)
I/requestLayout:ViewGroupGrandparent isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:ContentFrameLayout(空)
I/requestLayout:ContentFrameLayout isLayoutRequested = false(空)
I/requestLayout:ActionBarOverlayLayout(空)
I/requestLayout:ActionBarOverlayLayout isLayoutRequested = false(空)
I/requestLayout:FrameLayout(空)
I/requestLayout:FrameLayout isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:DecorView(空)
I/requestLayout:DecorView isLayoutRequested = false(空)
I/measure:ViewGroupGrandparent(空)
I/ViewGroupGrandparent:称为onMeasure的
I/措施:ViewGroupParent(空)
I/ViewGroupParent:onMeasure被称为
I/measure:MyChildView(1)
I/MyChildView:onMeasure称为(1)
I/measure:MyChildView(2)
I/ViewGroupGrandparent:onLayout被称为
I/ViewGroupParent:onLayout被称为
I/MyChildView:onLayout称为(1)
I/MyChildView:onDraw称为(1)

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 called
I/measure: ViewGroupParent (null)
I/ViewGroupParent: onMeasure called
I/measure: MyChildView (1)
I/measure: MyChildView (2)
I/ViewGroupGrandparent: onLayout called
I/ViewGroupParent: onLayout called
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 called
I/measure: ViewGroupParent (null)
I/ViewGroupParent: onMeasure called
I/measure: MyChildView (1)
I/MyChildView: onMeasure called (1)
I/measure: MyChildView (2)
I/ViewGroupGrandparent: onLayout called
I/ViewGroupParent: onLayout called
I/MyChildView: onLayout called (1)
I/MyChildView: onDraw called (1)

E部分-本部分进一步说明,仅requestLayout()调用的目标视图的直接后代似乎参与了触发的布局传递.第34和35行似乎表明嵌套视图可以链接.

Section E - This section further demonstrates that only direct descendents of the target view of a call to requestLayout() seems to participate in the triggered layout passes. Lines 34 and 35 seem to indicate that a nested views can chain.

这是E部分的日志:

I/MainActivity:32 ********************************************** *
I/requestLayout:ViewGroupGrandparent(空)
I/requestLayout:ViewGroupGrandparent isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:ContentFrameLayout(空)
I/requestLayout:ContentFrameLayout isLayoutRequested = false(空)
I/requestLayout:ActionBarOverlayLayout(空)
I/requestLayout:ActionBarOverlayLayout isLayoutRequested = false(空)
I/requestLayout:FrameLayout(空)
I/requestLayout:FrameLayout isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:DecorView(空)
I/requestLayout:DecorView isLayoutRequested = false(空)
I/measure:ViewGroupGrandparent(空)
I/ViewGroupGrandparent:称为onMeasure的
I/措施:ViewGroupParent(空)
I/ViewGroupGrandparent:onLayout被称为
I/MainActivity:33 ***********************************************
I/requestLayout:ViewGroupGrandparent(空)
I/requestLayout:ViewGroupGrandparent isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:ContentFrameLayout(空)
I/requestLayout:ContentFrameLayout isLayoutRequested = false(空)
I/requestLayout:ActionBarOverlayLayout(空)
I/requestLayout:ActionBarOverlayLayout isLayoutRequested = false(空)
I/requestLayout:FrameLayout(空)
I/requestLayout:FrameLayout isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:DecorView(空)
I/requestLayout:DecorView isLayoutRequested = false(空)
I/measure:ViewGroupGrandparent(空)
I/ViewGroupGrandparent:称为onMeasure的
I/措施:ViewGroupParent(空)
I/ViewGroupGrandparent:onLayout被称为
I/MainActivity:34 ***********************************************
I/requestLayout:ViewGroupGrandparent(空)
I/requestLayout:ViewGroupGrandparent isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:ContentFrameLayout(空)
I/requestLayout:ContentFrameLayout isLayoutRequested = false(空)
I/requestLayout:ActionBarOverlayLayout(空)
I/requestLayout:ActionBarOverlayLayout isLayoutRequested = false(空)
I/requestLayout:FrameLayout(空)
I/requestLayout:FrameLayout isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:DecorView(空)
I/requestLayout:DecorView isLayoutRequested = false(空)
I/measure:ViewGroupGrandparent(空)
I/ViewGroupGrandparent:称为onMeasure的
I/措施:ViewGroupParent(空)
I/ViewGroupParent:onMeasure被称为
I/measure:MyChildView(1)
I/measure:MyChildView(2)
I/ViewGroupGrandparent:onLayout被称为
I/ViewGroupParent:onLayout被称为
I/MainActivity:35 *******************************************
I/requestLayout:ViewGroupGrandparent(空)
I/requestLayout:ViewGroupGrandparent isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:ContentFrameLayout(空)
I/requestLayout:ContentFrameLayout isLayoutRequested = false(空)
I/requestLayout:ActionBarOverlayLayout(空)
I/requestLayout:ActionBarOverlayLayout isLayoutRequested = false(空)
I/requestLayout:FrameLayout(空)
I/requestLayout:FrameLayout isLayoutRequested = false(空)
I/requestLayout:LinearLayout(空)
I/requestLayout:LinearLayout isLayoutRequested = false(空)
I/requestLayout:DecorView(空)
I/requestLayout:DecorView isLayoutRequested = false(空)
I/measure:ViewGroupGrandparent(空)
I/ViewGroupGrandparent:onMeasure被称为
I/措施:ViewGroupParent(空)
I/ViewGroupParent:onMeasure被称为
I/measure:MyChildView(1)
I/MyChildView:onMeasure称为(1)
I/measure:MyChildView(2)
I/ViewGroupGrandparent:onLayout被称为
I/ViewGroupParent:onLayout被称为
I/MyChildView:onLayout称为(1)
I/MyChildView:onDraw称为(1)

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 called
I/measure: ViewGroupParent (null)
I/ViewGroupGrandparent: onLayout called
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 called
I/measure: ViewGroupParent (null)
I/ViewGroupGrandparent: onLayout called
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 called
I/measure: ViewGroupParent (null)
I/ViewGroupParent: onMeasure called
I/measure: MyChildView (1)
I/measure: MyChildView (2)
I/ViewGroupGrandparent: onLayout called
I/ViewGroupParent: onLayout called
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 called
I/measure: ViewGroupParent (null)
I/ViewGroupParent: onMeasure called
I/measure: MyChildView (1)
I/MyChildView: onMeasure called (1)
I/measure: MyChildView (2)
I/ViewGroupGrandparent: onLayout called
I/ViewGroupParent: onLayout called
I/MyChildView: onLayout called (1)
I/MyChildView: onDraw called (1)

这是我对forceLayout()的要点:当需要重新测量诸如TableLayout中的子项并且您不想在每个子项上调用requestLayout()时,请使用它-forceLayout()重量更轻,将避免递归. (请参见C节中的注释.)forceLayout()也可以用于在需要时强制重新测量特定的直接子对象,而这些子对象通常是无法测量的. forceLayout()不能单独工作,必须与对requestLayout()

So this is my take-away for forceLayout(): Use it when there are children that need to be re-measured such as in TableLayout and you don't want to call requestLayout() on each child - forceLayout() is lighter weight and will avoid recursion. (See notes in Section C.) forceLayout() can also be used to force a remeasurement specific direct children when needed when they would not ordinarily be measured. forceLayout() does not work alone and must be paired with appropriate calls to requestLayout()

这篇关于如何在Android中使用forceLayout()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆