View.inflate和LayoutInflater.inflate都是我们平时常用的方法,一直来回用也没有注意两者的区别,做一个列表让条目加上颜色的功能,使用View.inflate总是不能实现,于是找了下源码。
我们首先看一看View.inflate的调用:
public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
LayoutInflater factory = LayoutInflater.from(context);
return factory.inflate(resource, root);
}
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root){
/**
请仔细看这个位置,root != null,也就是说当我们在View.inflate中第三个参数
给的是null,那么attachToRoot就已经指定了false
*/
return inflate(resource, root, root != null);
}
下面是核心的部分:
if (root != null) {
if (DEBUG) {
System.out.println("Creating params from root: " +
root);
}
// Create layout params that match root, if supplied
params = root.generateLayoutParams(attrs);
if (!attachToRoot) {
// Set the layout params for temp if we are not
// attaching. (If we are, we use addView, below)
//只有当root不为空并且attachToRoot不为空时temp才会有赋值
temp.setLayoutParams(params);
}
}
if (DEBUG) {
System.out.println("-----> start inflating children");
}
// Inflate all children under temp against its context.
rInflateChildren(parser, temp, attrs, true);
if (DEBUG) {
System.out.println("-----> done inflating children");
}
// We are supposed to attach all the views we found (int temp)
// to root. Do that now.
if (root != null && attachToRoot) {
root.addView(temp, params);
}
从上面我们能看出,只有当root以及attachToRoot不为空时,temp会设置layoutParams,也就是说如果需要对列表的条目的父控件做处理,那么root我们必须设置不为空,但是列表中,我们不能给View.inflate设置root,因为无论使用listview还是recycleView,调用getVIew的时候就已经设置过父布局了,如果这个时候我们传入root,会报出 The specified child already has a parent. " "You must call removeView() on the child's parent first
所以解决方法:
1 使用LayoutInflater.from(viewGroup.getContext()).inflate(android.R.layout.aaa, viewGroup,false));
2 给你的布局多套用一层,你不是说最外层的设置不起作用了吗,只能绘制加进去的view,那么我就把我原来的父控件外面再套一层,使用的时候设置父控件下面一级的布局,当然这个会造成布局的过度重绘,不建议。