我们一般用下面这种方式来用xml构建View。
View view = LayoutInflater.from(context).inflate(resourceId, parent, attachToRoot);
resourceId是xml布局文件,parent是父布局,如果parent设置为空,则构建的View将是一个独立的个体,属性无效。如果parent不为空,设置attachToRoot为false,则属性值会依托于root构建,所以此时的xml根布局的属性有效,但是resourceId生成的View不是root的子布局。如果设置attachToRoot为true,此时属性值会依托于root构建,所以此时的xml根布局的属性有效,但是resourceId生成的view是root的子布局,通过addView实现。
attachToRoot的作用就是root.addView的动作,但是在Adapter.getView里面不用手动调用root.addView是因为Adapter已经帮我们做了, 所以如果我们在Adapter.getView里面传入attachToRoot为true的话,就会报错, 因为一个view不能attach两次。
代码中的实例:
如在ViewPager,RecyclerView等中如果通过LayoutInflater.from(context).inflate构建子View,需要传入parent,并且attachToRoot=false。因为传入了parent,源码来看LayoutInflater会通过createViewFromTag方法通过反射来构建这个xml的根布局,只有当parent不为空时才会调用params = root.generateLayoutParams(attrs);来生成根布局的LayoutParams,然后当attachToRoot为false时才去给根布局设置params参数。
上面如果传parent=null,那么你在子View的xml中写的根布局上的宽高等属性将失效。有些人遇到这问题,在子View外再套个布局虽然能解决,但是层级会变深,正确的做法应该是设置parent,attachToRoot=false。