LayoutInflater。膨胀文档对我来说并不完全清楚attachtorroot参数的用途。
attachtorroot:膨胀的层次结构是否应该附加到根参数?如果为false,则root仅用于创建正确的 XML中根视图的LayoutParams的子类。
有没有人能更详细地解释一下,具体地说,根视图是什么,也许还能举个例子,说明在真值和假值之间的行为变化?
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决定你是否想要膨胀器把它附加到父对象上。在某些情况下,这会导致问题,比如在ListAdapter中,它会导致一个异常,因为列表试图将视图添加到列表中,但它说它已经附加。在其他情况下,您只是自己膨胀视图以添加到活动,这可能很方便,并节省了一行代码。
如果设置为true,那么当你的布局膨胀时,它将自动添加到ViewGroup的视图层次结构中,在第二个参数中指定作为子参数。例如,如果根参数是线性布局,那么你的膨胀视图将自动添加为该视图的子视图。
如果它被设置为false,那么你的布局将被膨胀,但不会附加到任何其他布局(所以它不会被绘制,接收触摸事件等)。
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意味着inflatedView将被添加到父视图的层次结构中。因此,用户可能会“看到”并感知触摸事件(或任何其他UI操作)。否则,它只是被创建了,没有被添加到任何视图层次结构中,因此不能被看到或处理触摸事件。
对于刚接触Android的iOS开发者,attachtorroot设置为true意味着你调用这个方法:
[parent addSubview:inflatedView];
如果更进一步,你可能会问:如果我将attachtorroot设置为false,为什么我要传递父视图?这是因为XML树中的根元素需要父视图来计算一些LayoutParams(比如match parent)。
现在与否
“第三个”参数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。但我还没有测试过。