首页 > 代码库 > [Android] 转-LayoutInflater丢失View的LayoutParams

[Android] 转-LayoutInflater丢失View的LayoutParams

 

View view = inflater.inflate(R.layout.item, null);

在使用类似以上方法获取view时会遇到的一个问题就是布局文件中定义的LayoutParams被忽略了。以下三个stackoverflow问题就是这样:

http://stackoverflow.com/questions/5288435/layout-params-of-loaded-view-are-ignored

http://stackoverflow.com/questions/5026926/making-sense-of-layoutinflater

http://stackoverflow.com/questions/2738670/layoutinflater-ignoring-parameters

都说这样使用就可以了:

View view = inflater.inflate( R.layout.item /* resource id */, parent /* parent */,false /*attachToRoot*/);

至此问题已经解决了,但是三个问题都没有提到为什么要这样调用才行。

感兴趣的我们到源码里来找答案,LayoutInflater的inflate方法,最后都是调用的同一个方法:

public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)

原因自然在这个方法里,大概意思就是只有ViewGroup root不为空才会读取View的LayoutParams。attachToRoot = true的时候,会把View添加到root中。而大多情况不希望被addView到root中,自然要赋值为flase,这样就是上面的解决方案了。

可以参看LayoutInflater的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.,     *        <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 node. Throws     * {@link InflateException} if there is an error. *     * <p>     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance     * reasons, view inflation relies heavily on pre-processing of XML files     * that is done at build time. Therefore, it is not currently possible to     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.     *     * @param parser XML dom node containing the description of the view     *        hierarchy.     * @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(XmlPullParser parser, ViewGroup root) {        return inflate(parser, 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) {        if (DEBUG) System.out.println("INFLATING from resource: " + resource);        XmlResourceParser parser = getContext().getResources().getLayout(resource);        try {            return inflate(parser, root, attachToRoot);        } finally {            parser.close();        }    }    /**     * Inflate a new view hierarchy from the specified XML node. Throws     * {@link InflateException} if there is an error.     * <p>     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance     * reasons, view inflation relies heavily on pre-processing of XML files     * that is done at build time. Therefore, it is not currently possible to     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.     *     * @param parser XML dom node containing the description of the view     *        hierarchy.     * @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(XmlPullParser parser, ViewGroup root, boolean attachToRoot) {        synchronized (mConstructorArgs) {            final AttributeSet attrs = Xml.asAttributeSet(parser);            mConstructorArgs[0] = mContext;            View result = root;            try {                // Look for the root node.                int type;                while ((type = parser.next()) != XmlPullParser.START_TAG &&                        type != XmlPullParser.END_DOCUMENT) {                    // Empty                }                if (type != XmlPullParser.START_TAG) {                    throw new InflateException(parser.getPositionDescription()                            + ": No start tag found!");                }                final String name = parser.getName();                if (DEBUG) {                    System.out.println("**************************");                    System.out.println("Creating root view: "                            + name);                    System.out.println("**************************");                }                if (TAG_MERGE.equals(name)) {                    if (root == null || !attachToRoot) {                        throw new InflateException("<merge /> can be used only with a valid "                                + "ViewGroup root and attachToRoot=true");                    }                    rInflate(parser, root, attrs);                } else {                    // Temp is the root view that was found in the xml                    View temp = createViewFromTag(name, attrs);                    ViewGroup.LayoutParams params = null;                    if (root != null) {                        if (DEBUG) {                            System.out.println("Creating params from root: " +                                    root);                        }                        // Create layout params that match root, if supplied                        params = root.generateLayoutParams(attrs);                        if (!attachToRoot) {                            // Set the layout params for temp if we are not                            // attaching. (If we are, we use addView, below)                            temp.setLayoutParams(params);                        }                    }                    if (DEBUG) {                        System.out.println("-----> start inflating children");                    }                    // Inflate all children under temp                    rInflate(parser, temp, attrs);                    if (DEBUG) {                        System.out.println("-----> done inflating children");                    }                    // We are supposed to attach all the views we found (int temp)                    // to root. Do that now.                    if (root != null && attachToRoot) {                        root.addView(temp, params);                    }                    // Decide whether to return the root that was passed in or the                    // top view found in xml.                    if (root == null || !attachToRoot) {                        result = temp;                    }                }            } catch (XmlPullParserException e) {                InflateException ex = new InflateException(e.getMessage());                ex.initCause(e);                throw ex;            } catch (IOException e) {                InflateException ex = new InflateException(                        parser.getPositionDescription()                        + ": " + e.getMessage());                ex.initCause(e);                throw ex;            }            return result;        }    }

 

 

[Android] 转-LayoutInflater丢失View的LayoutParams