Android中使用LayoutInflater要注意的一些坑

LayoutInflater类在我们日常开发中经常会用到,最近在使用中就遇到了一些问题,所有下面这篇文章主要给大家总结了关于Android中使用LayoutInflater要注意的一些坑,希望通过这篇能让大家避免走一些弯路,需要的朋友可以参考学习,下面来一起看吧。

前言

在平时的开发过程中,我们经常会用LayoutInflater这个类,比如说在Fragment$onCreateViewRecyclerView.Adapter$onCreateViewHolder中都会用到。它的用法也无非就是LayoutInflater.inflate(resourceId, root, attachToRoot),第一个参数没什么好说的,但第二个和第三个参数结合起来会带来一定的迷惑性。之前有时候会发现界面布局上出了一些问题,查了很久之后偶然的改动了这两个参数,发现问题解决了,然后也就过去了,并没有去思考这是为什么,然后下次可能又重复这种困境了。

所以想在这里总结一下,避免以后继续掉坑。

先来看看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(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)

首先需要了解的一点是,一个View的测量结果并不只是由它自己的layout_width和layout_height(即LayoutParams)所决定的,而是由父容器给它的约束(MeasureSpec)和它自身的LayoutParams共同决定的。

达成这个共识之后,我们再来看看它的参数。

  • root:给布局文件提供一个父容器。布局文件里面总有一个元素是没有父容器的(没错,就是根元素),所以需要给它提供一个父容器来帮助它完成测量工作。如果root为空的话,就会导致根元素中的layout_xxx全部失效,从而影响到整个布局。同时,如果root为空的话,那么attachToRoot也就没有意义了。
  • attachToRoot: 如果为true,创建出来的布局系统会帮我们添加到父容器中去。为false的话,就只是给它提供约束,好让这个布局顺利完成测量等工作而已,将布局添加到父容器中去需要我们后续根据需要去手动调用addView方法。
  • 返回值:如果root != null && attachToRoot,返回的View就是传进来的root,否则返回由布局文件所创建的View对象。

用几个例子来说明一下会比较好理解。Activity的布局是一个LinearLayout,要添加的布局如下:

  

正常的情况

 // 第一种方法 View inflatedView = LayoutInflater.from(this).inflate(R.layout.item_text, mLinearLayout, true); Log.d(TAG, "inflated view is " + inflatedView); // 第二种方法 View inflatedView = LayoutInflater.from(this).inflate(R.layout.item_text, mLinearLayout, false); Log.d(TAG, "inflated view is " + inflatedView); mLinearLayout.addView(inflatedView);

视觉上的结果都是一样的


但是Log就有一点不一样了,这就是attachToRoot不同的值所导致的。

第一种方法的Log

 D/MainActivity: inflated view is android.widget.LinearLayout{36e9aac V.E...... ......I. 0,0-0,0 #7f0c0051 app:id/linear}

第二种方法的Log

 D/MainActivity: inflated view is android.support.v7.widget.AppCompatTextView{3c9d37b V.ED..... ......ID 0,0-0,0 #7f0c0054 app:id/item_text}

还有一个需要注意的地方是:如果在第一种方法的基础上再加上mLinearLayout.addView(inflatedView)就会造成报错
IllegalStateException: The specified child already has a parent....  。

而如果第二种方法没有这句话,界面上是看不到任何东西的。

root为null的情况

 mLinearLayout = (LinearLayout) findViewById(R.id.linear); View inflatedView = LayoutInflater.from(this).inflate(R.layout.item_text, null); Log.d(TAG, "inflated view is " + inflatedView); mLinearLayout.addView(inflatedView);

此时再看看它的布局文件:

  

不难发现,所有layout_xxx的属性全都失效了。

RecyclerView中的Inflater

上面说了,在创建布局的时候,要把布局添加到root中去,并且有两种方法,但是我们在onCreateViewHolder中添加布局的时候却是这样写的:

以上就是Android中使用LayoutInflater要注意的一些坑的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » 移动