Fragment onCreateView inflate注意事項
用Fragment很久了,今天忽然發現自己寫的東西,明明子Fragment是全屏,但是寬度只有那麼一點點。其實這個問題的本質是inflate的方法的使用,之前也研究過但麼有留下記錄,在fragment使用上又暴漏出來了。直覺告訴我一定是哪塊出問題了,很快鎖定到onCreateView上。
在onCreateView裡我們一般有兩種寫法,方法1:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View root = inflater.inflate(layoutId(), container, false);
return root;
}
方法2
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View root = inflater.inflate(layoutId(), null );
return root;
}
這兩種都可以,但是如果採用第二種,就不會繼承到母佈局的引數資訊。來看下文件:
/**
* 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.,
* <code>R.layout.main_page</code>)
* @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);
}
/**
* 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.,
* <code>R.layout.main_page</code>)
* @param root Optional view to be the parent of the generated hierarchy (if
* <em>attachToRoot</em> is true), or else simply an object that
* provides a set of LayoutParams values for root of the returned
* hierarchy (if <em>attachToRoot</em> 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最終呼叫了方法1,即inflate(int resource, ViewGroup root, boolean attachToRoot),所以直接看方法1.如果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,所以此處attachToRoot一定是false。
再反過來看,如果用了方法2,root一定要傳null,此時子view不會得到母view的佈局資訊,子view裡一堆的match_parent也就毫無用途。
總結:90%的情況下,我們使用fragment此處一定要用方法1. 有一種情況,如建立dialog fragment時,不需要得到母佈局引數資訊可以用方法2.
補充:上文程式碼裡的layoutId()是個虛擬函式,用來在子類裡實現。子類只需return R.layout.*就可以了,不必每個fragment都重寫onCreateView了。在onViewCreated里根據傳來的引數root去例項化各個控制元件。