Fragment onCreateView inflate注意事项 (整理)

用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:点击打开链接

你可能感兴趣的:(Android)