1. 程式人生 > >Fragment onCreateView inflate注意事項

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去例項化各個控制元件。