LayoutInflater。膨胀文档对我来说并不完全清楚attachtorroot参数的用途。
attachtorroot:膨胀的层次结构是否应该附加到根参数?如果为false,则root仅用于创建正确的 XML中根视图的LayoutParams的子类。
有没有人能更详细地解释一下,具体地说,根视图是什么,也许还能举个例子,说明在真值和假值之间的行为变化?
LayoutInflater。膨胀文档对我来说并不完全清楚attachtorroot参数的用途。
attachtorroot:膨胀的层次结构是否应该附加到根参数?如果为false,则root仅用于创建正确的 XML中根视图的LayoutParams的子类。
有没有人能更详细地解释一下,具体地说,根视图是什么,也许还能举个例子,说明在真值和假值之间的行为变化?
当前回答
当你定义父对象时,attachtorroot决定你是否想要膨胀器把它附加到父对象上。在某些情况下,这会导致问题,比如在ListAdapter中,它会导致一个异常,因为列表试图将视图添加到列表中,但它说它已经附加。在其他情况下,您只是自己膨胀视图以添加到活动,这可能很方便,并节省了一行代码。
其他回答
回复中似乎有很多文本,但没有代码,这就是为什么我决定用一个代码示例来恢复这个老问题,在几个回复中人们提到:
如果设置为true,那么当你的布局膨胀时,它将自动添加到ViewGroup的视图层次结构中,在第二个参数中指定作为子参数。
这在代码中的实际含义(大多数程序员都能理解)是:
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);
}
}
注意,前面的代码添加了布局R.layout。child_view作为MyCustomLayout的孩子,因为attachToRoot参数为真,并以完全相同的方式分配父布局参数,如果我将使用addView编程,或如果我在xml中这样做:
LinearLayout < > <视图…/ > ... LinearLayout < / >
下面的代码解释了当传递attachRoot为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);
在前面的代码中,你指定你想要myView是它自己的根对象,不附加到任何父对象,后来我们将它添加为LinearLayout的一部分,但暂时它是一个独立的(没有父)视图。
同样的事情也发生在Fragments上,你可以将它们添加到一个已经存在的组中并成为它的一部分,或者只是传递参数:
inflater. inflation (r.b ayout.fragment, null, false);
来指定它将是它自己的根。
例如我们有一个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。但我还没有测试过。
文档和之前的两个答案应该足够了,只是我的一些想法。
充气方法用于充气布局文件。有了这些膨胀的布局,你就有可能直接将它们附加到父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。
attachtorroot设置为true意味着inflatedView将被添加到父视图的层次结构中。因此,用户可能会“看到”并感知触摸事件(或任何其他UI操作)。否则,它只是被创建了,没有被添加到任何视图层次结构中,因此不能被看到或处理触摸事件。
对于刚接触Android的iOS开发者,attachtorroot设置为true意味着你调用这个方法:
[parent addSubview:inflatedView];
如果更进一步,你可能会问:如果我将attachtorroot设置为false,为什么我要传递父视图?这是因为XML树中的根元素需要父视图来计算一些LayoutParams(比如match parent)。