Android View与LayoutInflater

一、View

View组件是一个空白的矩形区域,并负责这块区域的界面绘制和事件处理。

Android中的所有UI组件类都继承了View类,扩展出具有各种形状和功能的UI组件。

View还有一个重要的子类:ViewGroup,通常作为其他组件的容器来使用,这些组件可以是View组件也可以是ViewGroup组件,当然,ViewGroup也可以作为一个View来使用。

二、LayoutInflater

当我们想要向一个ViewGroup里动态地添加View或者ViewGroup时,要使用LayoutInflater。

首先要获取LayoutInflater的实例,有两种方式:

LayoutInflater layoutInflater = LayoutInflater.from(context);
LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
其实第一种就是第二种封装后的简单写法。

然后,我们用这个实例调用inflater()方法去加载布局:

layoutInflater.inflate(int resource,ViewGroup root)

第一个参数是要加载布局的id,第二个参数指给该布局的外部再嵌套一层父布局。

从源码的角度来说,在这个Inflater()方法的内部,采用pull解析的方式去解析布局文件。调用createViewFromTag()这个方法返回传入的resource对应加载布局的最外层布局的View对象,然后在rInflater()这个方法遍历这个最外层布局下的子元素,同样通过createViewFromTag()这个方法创建这些子元素的View对象,并通过addView()添加到最外层布局中,最终返回这个resouse对应加载布局的View对象。如果这个root不为空,那么还会将这个这个加载布局的View对象add到root布局中再返回。


inflater()方法还有接收三个参数的方法重载

inflate(int resource, ViewGroup root, boolean attachToRoot)  
如果root为空,attachToRoot将失去作用,设置任何值都没有意义。

如果root不为空,attachToRoot为true,跟上面接收两个参数的inflate()方法中root参数不为空的情况一致。

如果root不为空,attachToRoot为false,不会为加载布局外部嵌套一层父布局,但是会对加载布局的最外层的layout属性预设置,当这个加载布局的View对象被add到另一个View时,这些layout属性会立即生效。这是什么意思呢?直接看源码:

 View temp = createViewFromTag(name, attrs);       
          if (root != null) { 
                  //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  
                        temp.setLayoutParams(params);  
                    }  
                }  

先来简单了解一下LayoutParams,我们都知道LayoutParams are used by views to tell their parents how they want to be laid out,即LayoutParams是由ParentView创建出来给ChildView用的,ChildView设置了LayoutParams后在ParentView addView的时候把这个LayoutParams传回给ParentVIew告诉它自己想要怎么设置。

通过上述代码,我们可以很清楚地看到,attrs里的layout属性通过root转化为LayoutParams对象,然后temp对它进行了提前的设置。看到这里,有的朋友可能会有一个疑问,这里LayoutParams是root这个布局的类型对应的,当我要把这个inflate方法返回的View对象add到另一个不同类型的布局的时候,比如,root是RelativeLayout类型,而调用addVIew()方法的是一个LinearLayout类型,这样不会报错吗?其实,在addView()这个方法内部有一个checkLayoutParam()方法会检查被添加的View的LayoutParam是否是调用addView()的View的布局类型对应的LayoutParams,如果不是,则会转化为后者对应的LayoutParams 。


我们都知道,View组件都必须存在一个布局中才可以设置一些layout类的属性,比如layout_height,layout_width等,如果没有存在于一个布局中,那么这些属性都将失效。在这里总结一下inflate()方法怎么用layout属性才会生效。

这里分两种情况,第一种情况,View组件在一个布局中,那么无论用哪一种inflate()方法,这个View组件的layout属性都可以生效。

第二种情况,View组件没有在一个布局中,那么root不为空的时候,无论用哪一种inflate()方法,addView()后这个View组件的layout属性都可以生效。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值