用Fragment很久了,今天忽然发现自己写的东西,明明子Fragment是全屏,但是宽度只有那么一点点。其实这个问题的本质是inflate的方法的使用,之前也研究过但没有留下记录,在fragment使用上又暴漏出来了。直觉告诉我一定是哪块出问题了,很快锁定到onCreateView上。
在onCreateView里我们一般有两种写法:
方法1:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View root = inflater.inflate(layoutId(), container, false);
return root;
}
方法2:
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View root = inflater.inflate(layoutId(), null);
return root;
}
这两种都可以,但是如果采用第二种,就不会继承到母布局的参数信息。来看下文档:
方法2调用的inflate()方法如下:
/**
* Inflate a new view hierarchy from the specified xml resource. Throws
* {@link InflateException} if there is an error.
*
* @param resource ID for an XML layout resource to load (e.g.,
* R.layout.main_page
)
* @param root Optional view to be the parent of the generated hierarchy.
* @return The root View of the inflated hierarchy. If root was supplied,
* this is the root View; otherwise it is the root of the inflated
* XML file.
*/
public View inflate(int resource, ViewGroup root) {
return inflate(resource, root, root != null);
}
方法1调用的inflate()方法如下:
/**
* Inflate a new view hierarchy from the specified xml resource. Throws
* {@link InflateException} if there is an error.
*
* @param resource ID for an XML layout resource to load (e.g.,
* R.layout.main_page
)
* @param root Optional view to be the parent of the generated hierarchy (if
* attachToRoot is true), or else simply an object that
* provides a set of LayoutParams values for root of the returned
* hierarchy (if attachToRoot is false.)
* @param attachToRoot Whether the inflated hierarchy should be attached to
* the root parameter? If false, root is only used to create the
* correct subclass of LayoutParams for the root view in the XML.
* @return The root View of the inflated hierarchy. If root was supplied and
* attachToRoot is true, this is root; otherwise it is the root of
* the inflated XML file.
*/
public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
final Resources res = getContext().getResources();
if (DEBUG) {
Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
+ Integer.toHexString(resource) + ")");
}
final XmlResourceParser parser = res.getLayout(resource);
try {
return inflate(parser, root, attachToRoot);
} finally {
parser.close();
}
}
方法2调用的inflate()方法最终调用了方法1中调用的inflate()方法,即在inflate(int resource, ViewGroup root)中调用了inflate(int resource, ViewGroup root, boolean attachToRoot),所以直接看方法1调用的inflate()方法.
如果root不为空,attachToRoot为false的情况下,文档说的很明白:If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML,即root只用来创建父布局的参数信息。而为true,则添加到父布局。因为我们控制fragment时要手动add/remove等,所以此处attachToRoot一定是false。
再反过来看,如果用了方法2,root一定要传null,此时子view不会得到母view的布局信息,子view里一堆的match_parent也就毫无用途。
总结:90%的情况下,我们使用fragment此处一定要用方法1. 有一种情况,如创建dialog fragment时,不需要得到母布局参数信息可以用方法2.
补充:上文代码里的layoutId()是个虚函数,用来在子类里实现。子类只需return R.layout.xxx就可以了,不必每个fragment都重写onCreateView了。在onViewCreated里根据传来的参数root去实例化各个控件。
原文URL:点击打开链接