LayoutInflater。膨胀文档对我来说并不完全清楚attachtorroot参数的用途。

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

有没有人能更详细地解释一下,具体地说,根视图是什么,也许还能举个例子,说明在真值和假值之间的行为变化?


当前回答

例如我们有一个ImageView,一个LinearLayout和一个RelativeLayout。LinearLayout是RelativeLayout的子元素。 视图层次结构将是。

RelativeLayout
           ------->LinearLayout

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

image_view_layout.xml

附根:

//here container is the LinearLayout

    View v = Inflater.Inflate(R.layout.image_view_layout,container,true);

这里v包含了容器布局的引用,即 LinearLayout。如果你想设置setImageResource(R.drawable.np)等参数;你必须通过父类的引用来找到它,即view.findById() v的父元素是FrameLayout。 LayoutParams将属于FrameLayout。

不连接到根:

//here container is the LinearLayout
    View v = Inflater.Inflate(R.layout.image_view_layout,container,false);

这里v包含的不是参考容器布局,而是直接布局 ImageView的引用是膨胀的,所以你可以设置它的 参数如view.setImageResource(R.drawable.np);没有 引用像findViewById。但是容器被指定了 ImageView获取容器的LayoutParams,你可以说 container的引用只是为了LayoutParams什么都没有 其他的事情。 所以在特定情况下Parent将为null。 LayoutParams将属于LinearLayout。

其他回答

现在与否

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

当你输入attachtorroot

true:立即将子视图添加到父视图 false:现在将子视图添加到父视图。 稍后再添加。`

什么时候?

后面就是使用parent。addview (childView)

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

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

等于

inflater.inflate(child,parent,true);

一个大禁忌 当您不负责将子视图添加到父视图时,永远不要将attachtorroot传递为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;
  }

如果你传递第三个参数为true,你会得到IllegalStateException,因为这个家伙。

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

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

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

attachtorroot设置为true:

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

假设我们在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>

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

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

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

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

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

让我们看看什么时候你想把attachtorroot设为false。在这个场景中,在inflation()的第一个参数中指定的View此时还没有附加到第二个参数中的ViewGroup。

回想一下前面的Button例子,我们想从布局文件中附加一个自定义Button到mLinearLayout。我们仍然可以通过为attachtorroot传递false来将我们的Button附加到mLinearLayout -我们只是随后自己手动添加它。

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

这两行代码等价于我们在前面为attachtorroot传递true时在一行代码中所写的内容。通过传入false,我们说我们还不想将我们的视图附加到根ViewGroup。我们说它会在其他时间点发生。在本例中,另一个时间点就是紧接在inflation下面使用的addView()方法。

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

attachtorroot设置为false(false是必需的) 当在onCreateView()中膨胀并返回一个片段的视图时,请确保为attachtorroot传入false。如果传入true,您将得到一个IllegalStateException,因为指定的子对象已经有了父对象。你应该已经指定Fragment的视图将被放回Activity中的位置。添加、删除和替换片段是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();
}

root_viewGroup容器将在你的活动中保存你的片段是在你的片段中的onCreateView()中给你的ViewGroup参数。它也是你传递给layoutinflater . inflation()的ViewGroup。然而,FragmentManager将处理将你的片段视图附加到这个ViewGroup。您不希望将它附加两次。设置attachtorroot为false。

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

为什么我们给我们的片段的父ViewGroup在第一个地方,如果我们不想附加在onCreateView()?为什么inflation()方法请求一个根视图组? 事实证明,即使我们没有立即将新膨胀的视图添加到它的父视图组中,我们仍然应该使用父视图的LayoutParams,以便新视图在最终附加时确定它的大小和位置。

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

我自己也很困惑膨胀方法中attachtorroot的真正目的是什么。在研究了一些UI后,我终于得到了答案:

家长:

在本例中是围绕视图对象的小部件/布局,您希望使用findViewById()进行膨胀。

attachToRoot:

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

希望这能澄清困惑

只是分享一些我在研究这个话题时遇到的问题,

除了公认的答案,我想提出一些可能会有所帮助的观点。

所以,当我使用attachtorroot为true时,返回的视图类型为ViewGroup,即父的根ViewGroup,它作为参数传递给了填充(layoutResource,ViewGroup, attachtorroot)方法,而不是传递的布局类型,但在attachtorroot为false时,我们得到了该layoutResource的根ViewGroup的函数返回类型。

让我用一个例子来解释:

如果我们有一个线性布局作为根布局,然后我们要添加TextView在它通过膨胀函数。

然后使用attachtorroot作为真正的膨胀函数返回一个LinearLayout类型的视图

而在使用attachtorroot作为虚假膨胀函数时,返回一个类型为TextView的视图

希望这一发现能有所帮助……

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

充气方法用于充气布局文件。有了这些膨胀的布局,你就有可能直接将它们附加到父ViewGroup上,或者只是从那个布局文件中膨胀视图层次结构,并在正常的视图层次结构之外使用它。

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

For the second option the returned View is the root ViewGroup from the layout file. If you remember our last discussion from the include-merge pair question this is one of the reasons for the merge's limitation(when a layout file with merge as root is inflated, you must supply a parent and attachedToRoot must be set to true). If you had a layout file with the root a merge tag and attachedToRoot was set to false then the inflate method will have nothing to return as merge doesn't have an equivalent. Also, as the documentation says, the inflate version with attachToRoot set to false is important because you can create the view hierarchy with the correct LayoutParams from 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:

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

这一行确保了膨胀的R.layout。row_layout文件在它的根ViewGroup上设置了来自AdapterView子类的正确LayoutParams。如果你不这样做,你可能会有一些问题与布局文件,如果根是RelativeLayout。tableelayout /TableRow也有一些特殊和重要的LayoutParams,你应该确保它们中的视图有正确的LayoutParams。