LayoutInflater。膨胀文档对我来说并不完全清楚attachtorroot参数的用途。
attachtorroot:膨胀的层次结构是否应该附加到根参数?如果为false,则root仅用于创建正确的 XML中根视图的LayoutParams的子类。
有没有人能更详细地解释一下,具体地说,根视图是什么,也许还能举个例子,说明在真值和假值之间的行为变化?
LayoutInflater。膨胀文档对我来说并不完全清楚attachtorroot参数的用途。
attachtorroot:膨胀的层次结构是否应该附加到根参数?如果为false,则root仅用于创建正确的 XML中根视图的LayoutParams的子类。
有没有人能更详细地解释一下,具体地说,根视图是什么,也许还能举个例子,说明在真值和假值之间的行为变化?
当前回答
现在与否
“第三个”参数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。但我还没有测试过。
其他回答
例如我们有一个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。
由于inflation()方法的文档,关于这个主题有很多困惑。
通常,如果attachtorroot被设置为true,那么第一个参数中指定的布局文件将被膨胀,并在那个时刻附加到第二个参数中指定的ViewGroup。当attachtorroot为false时,来自第一个参数的布局文件将膨胀并作为视图返回,任何视图附件都在其他时间发生。
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.
您可以在我写的一篇关于这个主题的博客文章中阅读其他几个关于对话框和自定义视图的独特示例。
https://www.bignerdranch.com/blog/understanding-androids-layoutinflater-inflate/
当你定义父对象时,attachtorroot决定你是否想要膨胀器把它附加到父对象上。在某些情况下,这会导致问题,比如在ListAdapter中,它会导致一个异常,因为列表试图将视图添加到列表中,但它说它已经附加。在其他情况下,您只是自己膨胀视图以添加到活动,这可能很方便,并节省了一行代码。
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为true时,返回的视图类型为ViewGroup,即父的根ViewGroup,它作为参数传递给了填充(layoutResource,ViewGroup, attachtorroot)方法,而不是传递的布局类型,但在attachtorroot为false时,我们得到了该layoutResource的根ViewGroup的函数返回类型。
让我用一个例子来解释:
如果我们有一个线性布局作为根布局,然后我们要添加TextView在它通过膨胀函数。
然后使用attachtorroot作为真正的膨胀函数返回一个LinearLayout类型的视图
而在使用attachtorroot作为虚假膨胀函数时,返回一个类型为TextView的视图
希望这一发现能有所帮助……