Android LayoutInflater attachToRoot 参数是什么意思?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12567578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:03:03  来源:igfitidea点击:

What does the LayoutInflater attachToRoot parameter mean?

androidandroid-layoutandroid-viewlayout-inflater

提问by Jeff Axelrod

The LayoutInflater.inflatedocumentation isn't exactly clear to me about the purpose of the attachToRootparameter.

LayoutInflater.inflate文档是不完全清楚,我对目的attachToRoot参数。

attachToRoot: whether the inflated hierarchy should be attached to the root parameter? If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML.

attachToRoot:膨胀的层次结构是否应该附加到根参数?如果为 false,则 root 仅用于为 XML 中的根视图创建 LayoutParams 的正确子类。

Could someone please explain in more detail, specifically what the root view is, and maybe show an example of a change in behavior between trueand falsevalues?

有人可以更详细地解释一下,特别是根视图是什么,也许可以展示一个truefalse值之间行为变化的例子?

回答by Rohit Singh

NOW OR NOT NOW

现在或不现在

The main difference between the "third" parameter attachToRoot being true or false is this.

“第三个”参数 attachToRoot 是真还是假的主要区别是这个。

When you put attachToRoot

当你把 attachToRoot

true :add the child view to parent RIGHT NOW
false:add the child view to parent NOT NOW.
Add it later. `

真:添加子视图父现在
假的:子视图添加到父不是现在
稍后再添加。`

When is that later?

如果是

That later is when you use for eg parent.addView(childView)

稍后是当你使用例如 parent.addView(childView)

A common misconceptionis, if attachToRoot parameter is false then the child view will not be added to parent. WRONG
In both cases, child view will be added to parentView. It is just the matter of time.

一个常见的误解是,如果 attachToRoot 参数为 false,则子视图将不会添加到父视图。错误
在这两种情况下,子视图都将添加到父视图。这只是时间问题

inflater.inflate(child,parent,false);
parent.addView(child);   

is equivalent to

相当于

inflater.inflate(child,parent,true);

A BIG NO-NO
You should never pass attachToRoot as true when you are not responsible for adding the child view to parent.
Eg When adding Fragment

一个
很大的禁忌 当您不负责将子视图添加到父视图时,您不应该将 attachToRoot 传递为 true。
例如添加片段时

public View onCreateView(LayoutInflater inflater,ViewGroup parent,Bundle bundle)
  {
        super.onCreateView(inflater,parent,bundle);
        View view = inflater.inflate(R.layout.image_fragment,parent,false);
        .....
        return view;
  }

if you pass third parameter as true you will get IllegalStateException because of this guy.

如果你将第三个参数作为 true 传递,你会因为这个人而得到 IllegalStateException。

getSupportFragmentManager()
      .beginTransaction()
      .add(parent, childFragment)
      .commit();

Since you have already added the child fragment in onCreateView() by mistake. Calling add will tell you that child view is already added to parent Hence IllegalStateException.
Here you are not responsible for adding childView, FragmentManager is responsible. So always pass false in this case.

由于您已经错误地在 onCreateView() 中添加了子片段。调用 add 会告诉您子视图已经添加到父视图中,因此IllegalStateException
这里你不负责添加childView,FragmentManager负责。所以在这种情况下总是传递 false 。

NOTE:I have also read that parentView will not get childView touchEvents if attachToRoot is false. But I have not tested it though.

注意:我还读到如果 attachToRoot 为 false,parentView 将不会获得 childView touchEvents。但我还没有测试过。

回答by Joseph Earl

If set to true then when your layout is inflated it will be automatically added to the view hierarchy of the ViewGroup specified in the 2nd parameter as a child. For example if the root parameter was a LinearLayoutthen your inflated view will be automatically added as a child of that view.

如果设置为 true,那么当您的布局膨胀时,它将作为子项自动添加到第二个参数中指定的 ViewGroup 的视图层次结构中。例如,如果 root 参数是 a,LinearLayout那么您的膨胀视图将自动添加为该视图的子视图。

If it is set to false then your layout will be inflated but won't be attached to any other layout (so it won't be drawn, receive touch events etc).

如果它被设置为 false 那么你的布局将被膨胀但不会附加到任何其他布局(所以它不会被绘制,接收触摸事件等)。

回答by Martin Cazares

Seems like a lot of text in the responses but no code, that's why I decided to revive this old question with a code example, in several responses people mentioned:

回复中似乎有很多文本但没有代码,这就是为什么我决定用代码示例来重温这个老问题,在人们提到的几个回复中:

If set to true then when your layout is inflated it will be automatically added to the view hierarchy of the ViewGroup specified in the 2nd parameter as a child.

如果设置为 true,那么当您的布局膨胀时,它将作为子项自动添加到第二个参数中指定的 ViewGroup 的视图层次结构中。

What that actually means in code(what most programmers understand) is:

这在代码中的实际含义(大多数程序员理解的)是:

public class MyCustomLayout extends LinearLayout {
    public MyCustomLayout(Context context) {
        super(context);
        // Inflate the view from the layout resource and pass it as child of mine (Notice I'm a LinearLayout class).

        LayoutInflater.from(context).inflate(R.layout.child_view, this, true);
    }
}

Notice that previous code is adding the layout R.layout.child_viewas child of MyCustomLayoutbecause of attachToRootparam is trueand assigns the layout params of the parent exactly in the same way as if I would be using addViewprogrammatically, or as if I did this in xml:

请注意,前面的代码将布局添加R.layout.child_view为子项,MyCustomLayout因为attachToRootparam istrue并以与我以addView编程方式使用完全相同的方式分配父项的布局参数,或者就像我在 xml 中执行此操作一样:

<LinearLayout>
   <View.../>
   ...
</LinearLayout>
<LinearLayout>
   <View.../>
   ...
</LinearLayout>

The following code explains the scenario when passing attachRootas false:

以下代码解释了传递attachRootas时的场景false

LinearLayout linearLayout = new LinearLayout(context);
linearLayout.setLayoutParams(new LayoutParams(
    LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
linearLayout.setOrientation(LinearLayout.VERTICAL);
    // Create a stand-alone view
View myView = LayoutInflater.from(context)
    .inflate(R.layout.ownRootView, null, false);
linearLayout.addView(myView);

In the previous code you specify that you wanted myViewto be it's own root object and do not attach it to any parent, later on we added it as part of the LinearLayoutbut for a moment it was a stand-alone (no parent) view.

在前面的代码中,您指定myView要成为它自己的根对象并且不将其附加到任何父对象,稍后我们将其添加为 的一部分,LinearLayout但有一段时间它是一个独立(无父)视图。

Same thing happens with Fragments, you could add them to an already existing group and be part of it, or just pass the parameters:

Fragments 也会发生同样的事情,你可以将它们添加到一个已经存在的组并成为它的一部分,或者只传递参数:

inflater.inflate(R.layout.fragment, null, false);

inflater.inflate(R.layout.fragment, null, false);

To specify that it will be it's own root.

指定它将是它自己的根。

回答by Luksprog

The documentation and the two previous answers should be enough, just some thoughts from me.

文档和前两个答案应该足够了,只是我的一些想法。

The inflatemethod is used to inflate layout files. With those inflated layouts you have to possibility to attach them directly to a parent ViewGroupor just inflate the view hierarchy from that layout file and work with it outside of the normal view hierarchy.

inflate方法用于膨胀布局文件。使用这些膨胀的布局,您必须有可能将它们直接附加到父级,ViewGroup或者只是从该布局文件膨胀视图层次结构,并在正常视图层次结构之外使用它。

In the first case the attachToRootparameter will have to be set to true(or much simple use the inflatemethod that takes a layout file and a parent root ViewGroup(non null)). In this case the Viewreturned is simply the ViewGroupthat was passed in the method, the ViewGroupto which the inflated view hierarchy will be added.

在第一种情况下,attachToRoot必须将参数设置为true(或者更简单地使用inflate采用布局文件和父根ViewGroup(非null)的方法)。在这种情况下,View返回的只是ViewGroup方法中传递的 ,ViewGroup膨胀的视图层次结构将添加到其中。

For the second option the returned Viewis the root ViewGroupfrom the layout file. If you remember our last discussion from the include-mergepair questionthis is one of the reasons for the merge's limitation(when a layout file with mergeas root is inflated, you must supply a parent and attachedToRootmust be set to true). If you had a layout file with the root a mergetag and attachedToRootwas set to falsethen the inflatemethod will have nothing to return as mergedoesn't have an equivalent. Also, as the documentation says, the inflateversion with attachToRootset to falseis important because you can create the view hierarchy with the correct LayoutParamsfrom the parent. This is important in some cases, most notable with the children of AdapterView, a subclass of ViewGroup, for which the addView()methods set is not supported. I'm sure you recall using this line in the getView()method:

对于第二个选项,返回的ViewViewGroup布局文件的根。如果您还记得我们在include-merge配对问题中的最后讨论,这就是merge's 限制的原因之一(当merge以 root 身份attachedToRoot扩展的布局文件时,您必须提供一个父项并且必须设置为true)。如果您有一个布局文件,其根为 amerge标记并attachedToRoot设置为,false则该inflate方法将没有任何返回值,因为merge没有等效项。此外,正如文档所说,设置为的inflate版本很重要,因为您可以使用正确的方式创建视图层次结构attachToRootfalseLayoutParams从父母。这在某些情况下很重要,最显着的是AdapterView的子类 的子类ViewGroup,其中addView()不支持方法集。我确定你记得在getView()方法中使用过这一行:

convertView = inflater.inflate(R.layout.row_layout, parent, false);

This line ensures that the inflated R.layout.row_layoutfile has the correct LayoutParamsfrom the AdapterViewsubclass set on its root ViewGroup. If you wouldn't be doing this you could have some problems with the layout file if the root was a RelativeLayout. The TableLayout/TableRowalso have some special and important LayoutParamsand you should make sure the views in them have the correct LayoutParams.

这一行确保膨胀的R.layout.row_layout文件在其根上具有正确LayoutParamsAdapterView子类集ViewGroup。如果您不这样做,如果根目录是RelativeLayout. 该TableLayout/TableRow也有一些特殊的,重要的LayoutParams,你应该确保在他们的观点有正确的LayoutParams

回答by Umer Farooq

I myself was also confused about what was the real purpose of attachToRootin inflatemethod. After a bit of UI study, I finally got the answer:

我自己也对attachToRootininflate方法的真正目的感到困惑。经过一番UI研究,我终于得到了答案:

parent:

家长:

in this case is the widget/layout that is surrounding the view objects that you want to inflate using findViewById().

在这种情况下,是围绕要使用 findViewById() 膨胀的视图对象的小部件/布局。

attachToRoot:

附加到根:

attaches the views to their parent (includes them in the parent hierarchy), so any touch event that the views recieve will also be transfered to parent view. Now it's upto the parent whether it wants to entertain those events or ignore them.if set to false, they are not added as direct children of the parent and the parent doesn't recieve any touch events from the views.

将视图附加到它们的父视图(包括它们在父层次结构中),因此视图收到的任何触摸事件也将转移到父视图。现在由父母决定是否要娱乐这些事件或忽略它们。如果设置为 false,它们不会被添加为父级的直接子级,并且父级不会从视图接收任何触摸事件。

Hope this clears the confusion

希望这能消除混乱

回答by capt.swag

I wrote this answer because even after going through several StackOverflow pages I wasn't able to clearly grasp what attachToRoot meant. Below is inflate() method in the LayoutInflater class.

我写这个答案是因为即使在浏览了几个 StackOverflow 页面之后,我也无法清楚地理解 attachToRoot 的含义。下面是 LayoutInflater 类中的 inflate() 方法。

View inflate (int resource, ViewGroup root, boolean attachToRoot)

Take a look at activity_main.xmlfile, button.xmllayout and the MainActivity.javafile I created.

查看activity_main.xml文件、button.xml布局和我创建的MainActivity.java文件。

activity_main.xml

活动_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

</LinearLayout>

button.xml

按钮.xml

<Button xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

MainActivity.java

主活动.java

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    LayoutInflater inflater = getLayoutInflater();
    LinearLayout root = (LinearLayout) findViewById(R.id.root);
    View view = inflater.inflate(R.layout.button, root, false);
}

When we run the code, we won't see the button in the layout. This is because our button layout is not added into the main activity layout since attachToRoot is set to false.

当我们运行代码时,我们不会在布局中看到按钮。这是因为我们的按钮布局没有添加到主活动布局中,因为 attachToRoot 设置为 false。

LinearLayout has an addView(View view)method which can be used to add Views to LinearLayout. This will add the button layout into the main activity layout, and make the button visible when you run the code.

LinearLayout 有一个addView(View view)方法,可用于将视图添加到 LinearLayout。这会将按钮布局添加到主活动布局中,并在运行代码时使按钮可见。

root.addView(view);

Let's remove the previous line, and see what happens when we set attachToRoot as true.

让我们删除前一行,看看当我们将 attachToRoot 设置为 true 时会发生什么。

View view = inflater.inflate(R.layout.button, root, true);

Again we see that the button layout is visible. This is because attachToRoot directly attaches the inflated layout to the parent specified. Which in this case is root LinearLayout. Here we don't have to add the views manually like we did in the previous case with addView(View view) method.

我们再次看到按钮布局是可见的。这是因为 attachToRoot 直接将膨胀的布局附加到指定的父级。在这种情况下是根 LinearLayout。在这里,我们不必像之前使用 addView(View view) 方法那样手动添加视图。

Why are people getting IllegalStateException when setting attachToRoot as true for a Fragment.

为什么人们在将片段的 attachToRoot 设置为 true 时会收到 IllegalStateException。

This is because for a fragment you have already specified where to place your fragment layout in your activity file.

这是因为对于片段,您已经指定了在活动文件中放置片段布局的位置。

FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
    .add(R.id.root, fragment)
    .commit();

The add(int parent, Fragment fragment)adds the fragment which has it's layout to the parent layout. If we set attachToRoot as true, you will get IllegalStateException: The specified child already has a parent. Since fragment layout is already added to the parent layout in the add() method.

插件(INT父母,片段片段)增加了它有它的布局父布局的片段。如果我们将 attachToRoot 设置为 true,您将得到 IllegalStateException: The specified child already have a parent。由于片段布局已经在 add() 方法中添加到父布局中。

You should always pass false for attachToRoot when you're inflating Fragments. It is the FragmentManager's job to add, remove and replace Fragments.

在给 Fragments 充气时,您应该始终为 attachToRoot 传递 false。添加、删除和替换 Fragment 是 FragmentManager 的工作。

Back to my example. What if we do both.

回到我的例子。如果我们两者都做怎么办。

View view = inflater.inflate(R.layout.button, root, true);
root.addView(view);

In the first line, LayoutInflater attaches the button layout to the root layout and returns a View object which holds the same button layout. In the second line, we add the same View object to the parent root layout. This results in the same IllegalStateException we saw with Fragments (The specified child already has a parent).

在第一行中,LayoutInflater 将按钮布局附加到根布局并返回一个包含相同按钮布局的 View 对象。在第二行中,我们将相同的 View 对象添加到父根布局中。这会导致我们在 Fragments 中看到的相同的 IllegalStateException(指定的孩子已经有一个父母)。

Keep in mind that there is another overloaded inflate() method, which sets attachToRoot as true by default.

请记住,还有另一个重载的 inflate() 方法,它默认将 attachToRoot 设置为 true。

View inflate (int resource, ViewGroup root)

回答by seanjfarrell

There is a lot of confusion on this topic due to the documentation for the inflate() method.

由于 inflate() 方法的文档,关于这个主题有很多混淆。

In general, if attachToRoot is set to true, then the layout file specified in the first parameter is inflated and attached to the ViewGroup specified in the second parameter at that moment in time. When attachToRoot is false, the layout file from the first parameter is inflated and returned as a View and any View attachment happens at some other time.

一般情况下,如果 attachToRoot 设置为 true,那么第一个参数中指定的布局文件会在那个时刻被膨胀并附加到第二个参数中指定的 ViewGroup。当 attachToRoot 为 false 时,第一个参数中的布局文件将膨胀并作为 View 返回,并且任何 View 附件都会在其他时间发生。

This probably doesn't mean much unless you see a lot of examples. When calling LayoutInflater.inflate() inside of the onCreateView method of a Fragment, you will want to pass in false for attachToRoot because the Activity associated with that Fragment is actually responsible for adding that Fragment's view. If you are manually inflating and adding a View to another View at some later point in time, such as with the addView() method, you will want to pass in false for attachToRoot because the attachment comes at a later point in time.

除非您看到很多示例,否则这可能没有多大意义。在 Fragment 的 onCreateView 方法内调用 LayoutInflater.inflate() 时,您需要为 attachToRoot 传入 false,因为与该 Fragment 关联的 Activity 实际上负责添加该 Fragment 的视图。如果您在稍后的某个时间点手动膨胀并将视图添加到另一个视图,例如使用 addView() 方法,您将需要为 attachToRoot 传递 false,因为附件在稍后的时间点出现。

You can read about several other unique examples concerning Dialogs and custom Views on a blog post I wrote about this very topic.

您可以在我写的有关此主题的博客文章中阅读有关对话框和自定义视图的其他几个独特示例。

https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/

https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/

回答by Alston

attachToRootset to true means the inflatedViewwill be added to the parent view's hierarchy. Thus can possibly be "seen" and sense touch events (or any other UI operations) by users. Otherwise, it is just been created, not been added to any view hierarchy and thus cannot be seen or handle touch events.

attachToRoot设置为 true 意味着inflatedView将被添加到父视图的层次结构中。因此,用户可能会“看到”并感知触摸事件(或任何其他 UI 操作)。否则,它只是被创建,没有被添加到任何视图层次结构中,因此无法看到或处理触摸事件。

For iOS developers new to Android, attachToRootset to true means you call this method:

对于刚接触 Android 的 iOS 开发人员,attachToRoot设置为 true 意味着您调用此方法:

[parent addSubview:inflatedView];

If going further you might ask: Why should I pass parent view if I set attachToRootto false? It is because the root element in your XML tree needs the parent view to calculate some LayoutParams (like match parent).

如果更进一步,您可能会问:如果我设置attachToRoot为 ,为什么要传递父视图false?这是因为 XML 树中的根元素需要父视图来计算一些 LayoutParams(例如匹配父级)。

回答by Faisal Naseer

For example we have an ImageView, a LinearLayoutand a RelativeLayout. LinearLayout is the child of RelativeLayout. the View Hierarchy will be.

例如,我们有 a ImageView、 aLinearLayout和 a RelativeLayout。LinearLayout 是 RelativeLayout 的子代。视图层次结构将是。

RelativeLayout
           ------->LinearLayout

and we have a separate layout file for ImageView

我们有一个单独的 ImageView 布局文件

image_view_layout.xml

image_view_layout.xml

Attach to root:

附加到根:

//here container is the LinearLayout

    View v = Inflater.Inflate(R.layout.image_view_layout,container,true);
  1. Here v contains the reference of the container layout i.e the LinearLayout.and if you want to set the parameters like setImageResource(R.drawable.np);of ImageView you will have to find it by the reference of parent i.e view.findById()
  2. Parent of v will be the FrameLayout.
  3. LayoutParams will be of FrameLayout.
  1. 这里 v 包含容器布局的引用,即 LinearLayout.and 如果你想设置像setImageResource(R.drawable.np);ImageView这样的参数,你必须通过父级的引用来找到它,即view.findById()
  2. v 的父级将是 FrameLayout。
  3. LayoutParams 将属于 FrameLayout。

Not attach to root:

不附加到根:

//here container is the LinearLayout
    View v = Inflater.Inflate(R.layout.image_view_layout,container,false);
  1. Here v contains the no reference container layout but direct reference to the ImageView that is inflated so you can set its parameters like view.setImageResource(R.drawable.np);without refereing like findViewById. But container is specified so that ImageView gets the LayoutParams of the container so you can say that the reference of container is just for LayoutParams nothing else.
  2. so in particular case Parent will be null.
  3. LayoutParams will be of LinearLayout.
  1. 这里 v 包含无引用容器布局,但直接引用膨胀的 ImageView,因此您可以像view.setImageResource(R.drawable.np);不引用一样设置其参数findViewById。但是指定了容器,以便 ImageView 获取容器的 LayoutParams,因此您可以说容器的引用仅用于 LayoutParams。
  2. 所以在特殊情况下 Parent 将为空。
  3. LayoutParams 将是 LinearLayout。

回答by Utshaw

attachToRoot Set to true:

attachToRoot 设置为 true:

If attachToRoot is set to true, then the layout file specified in the first parameter is inflated and attached to the ViewGroup specified in the second parameter.

如果 attachToRoot 设置为 true,则第一个参数中指定的布局文件将膨胀并附加到第二个参数中指定的 ViewGroup。

Imagine we specified a button in an XML layout file with its layout width and layout height set to match_parent.

想象一下,我们在 XML 布局文件中指定了一个按钮,其布局宽度和布局高度设置为 match_parent。

<Button xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/custom_button">
</Button>

We now want to programmatically add this Button to a LinearLayout inside of a Fragment or Activity. If our LinearLayout is already a member variable, mLinearLayout, we can simply add the button with the following:

我们现在想以编程方式将此 Button 添加到 Fragment 或 Activity 内的 LinearLayout。如果我们的 LinearLayout 已经是一个成员变量 mLinearLayout,我们可以简单地添加以下按钮:

inflater.inflate(R.layout.custom_button, mLinearLayout, true);

We specified that we want to inflate the Button from its layout resource file; we then tell the LayoutInflater that we want to attach it to mLinearLayout. Our layout parameters are honored because we know the Button gets added to a LinearLayout. The Button's layout params type should be LinearLayout.LayoutParams.

我们指定我们要从其布局资源文件中膨胀按钮;然后我们告诉 LayoutInflater 我们想要将它附加到 mLinearLayout。我们的布局参数受到尊重,因为我们知道 Button 被添加到 LinearLayout。Button 的布局参数类型应为 LinearLayout.LayoutParams。

attachToRoot Set to false (not required to use false)

attachToRoot 设置为false(不需要使用false)

If attachToRoot is set to false, then the layout file specified in the first parameter is inflated and notattached to the ViewGroup specified in the second parameter but that inflated view acquires parent's LayoutParamswhich enables that view to fit correctly in the parent.

如果 attachToRoot 设置为 false,则第一个参数中指定的布局文件会被膨胀,并且不会附加到第二个参数中指定的 ViewGroup,但膨胀的视图会获取父视图的 LayoutParams,从而使该视图能够正确地适合父视图。



Let's take a look at when you would want to set attachToRoot to false. In this scenario, the View specified in the first parameter of inflate() is not attached to the ViewGroup in the second parameter at this point in time.

让我们看看您何时需要将 attachToRoot 设置为 false。在这种情况下,inflate() 的第一个参数中指定的 View 此时没有附加到第二个参数中的 ViewGroup。

Recall our Button example from earlier, where we want to attach a custom Button from a layout file to mLinearLayout. We can still attach our Button to mLinearLayout by passing in false for attachToRoot—we just manually add it ourselves afterward.

回想一下之前的 Button 示例,我们希望将布局文件中的自定义 Button 附加到 mLinearLayout。我们仍然可以通过为 attachToRoot 传入 false 来将我们的 Button 附加到 mLinearLayout——我们只是在之后手动添加它。

Button button = (Button) inflater.inflate(R.layout.custom_button,    mLinearLayout, false);
mLinearLayout.addView(button);

These two lines of code are equivalent to what we wrote earlier in one line of code when we passed in true for attachToRoot. By passing in false, we say that we do not want to attach our View to the root ViewGroup just yet. We are saying that it will happen at some other point in time. In this example, the other point in time is simply the addView() method used immediately below inflation.

这两行代码相当于我们之前在为 attachToRoot 传入 true 时在一行代码中编写的内容。通过传入 false,我们表示我们暂时不想将我们的 View 附加到根 ViewGroup。我们是说它会在其他时间点发生。在这个例子中,另一个时间点只是在通货膨胀下面使用的 addView() 方法。

The false attachToRoot example requires a bit more work when we manually add the View to a ViewGroup.

当我们手动将 View 添加到 ViewGroup 时,false attachToRoot 示例需要更多的工作。

attachToRoot Set to false(false is Required)

When inflating and returning a Fragment's View in onCreateView(), be sure to pass in false for attachToRoot. If you pass in true, you will get an IllegalStateException because the specified child already has a parent. You should have specified where your Fragment's view will be placed back in your Activity. It is the FragmentManager's job to add, remove and replace Fragments.

attachToRoot 设置为false(false 为必填项)

在onCreateView() 中inflating 并返回Fragment 的View 时,一定要为attachToRoot 传入false。如果你传入 true,你会得到一个 IllegalStateException,因为指定的孩子已经有一个父母。您应该已指定将 Fragment 的视图放回 Activity 的位置。添加、删除和替换 Fragment 是 FragmentManager 的工作。

FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment =  fragmentManager.findFragmentById(R.id.root_viewGroup);

if (fragment == null) {
fragment = new MainFragment();
fragmentManager.beginTransaction()
    .add(R.id.root_viewGroup, fragment)
    .commit();
}

The root_viewGroup container that will hold your Fragment in your Activity is the ViewGroup parameter given to you in onCreateView() in your Fragment. It's also the ViewGroup you pass into LayoutInflater.inflate(). The FragmentManager will handle attaching your Fragment's View to this ViewGroup, however. You do not want to attach it twice. Set attachToRoot to false.

将在您的 Activity 中保存您的 Fragment 的 root_viewGroup 容器是在您的 Fragment 中的 onCreateView() 中提供给您的 ViewGroup 参数。它也是您传入 LayoutInflater.inflate() 的 ViewGroup。但是,FragmentManager 将处理将您的 Fragment 的视图附加到此 ViewGroup。您不想将其附加两次。将 attachToRoot 设置为 false。

public View onCreateView(LayoutInflater inflater, ViewGroup  parentViewGroup, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_layout,     parentViewGroup, false);
…
return view;
}

Why are we given our Fragment's parent ViewGroup in the first place if we don't want to attach it in onCreateView()? Why does the inflate() method request a root ViewGroup?

It turns out that even when we are not immediately adding our newly inflated View to its parent ViewGroup, we should still use the parent's LayoutParams in order for the new View to determine its size and position whenever it is eventually attached.

如果我们不想在 onCreateView() 中附加它,为什么我们首先给了 Fragment 的父 ViewGroup?为什么 inflate() 方法请求一个根 ViewGroup?

事实证明,即使我们没有立即将新膨胀的 View 添加到其父 ViewGroup,我们仍然应该使用父的 LayoutParams,以便新 View 在最终附加时确定其大小和位置。

Link: https://youtu.be/1Y0LlmTCOkM?t=409

链接:https: //youtu.be/1Y0LlmTCOkM?t=409