LayoutInflater解析

LayoutInflater解析:看了几篇博客巩固了自己的理解,说说自己对LayoutInflater浅显的理解:


常用读取xml,生成view的方法:

View view = View.inflate(context,resource,null);

进一步查看源码:其实调用的是LayoutInflater

public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
  LayoutInflater factory = LayoutInflater.from(context); //这里需要一个上下文
  return factory.inflate(resource, root);//调用的是LayoutInflater的inflate方法.

//也就是常用的LayoutInflater.from(context).inflate
//等于LayoutInflater.getService.inflate
}

再进一步查看
可以看出,LayoutInflater,其实是通过Context的getSystemService获取到的系统服务对象,

public static layoufrom(Context context) {
//context.getSystemService,这不是activity里获取系统服务类的方法么.
  LayoutInflater LayoutInflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  if (LayoutInflater == null) { //如果拿不到这个服务类就会抛出异常.
      throw new AssertionError("LayoutInflater not found.");
  } 
  return LayoutInflater;
}

总结:

//例1.生成view,但不指定父容器,如果父容器为null,那么设置ture还是false结果都一样
LayoutInflater.from(context).inflate(id,null);
//例2.结果和1一样,
LayoutInflater.from(context).inflate(id,null,false);
//例3.结果和1一样
LayoutInflater.from(context).inflate(id,null,true);
//例4.生成view,指定父容器,并添加到其中,获取parent的Layoutparmas设置view的Layoutparmas.
LayoutInflater.from(context).inflate(id,parent,true);
//例5.生成view,指定父容器,不添加到其中,获取parent的Layoutparmas设置view的Layoutparmas.
LayoutInflater.from(context).inflate(id,parent,false);

用例1,2,3生成的view是没有Layoutparmas的.所以必须手动设置,不然xml里面设置的属性会失效
用例4,5设生成的view,不管设置的true还是false,生成的view都会从parent中得到Layoutparmas,区别在于,是否添加到parent中
如果使用例4,则不要再去parent.addview(),否则会抛出异常


踩坑分析:

LinearLayout layout = (LinearLayout)findViewById(R.id.container);
View view = View.inflate(this, R.layout.layout_menu_item, null);
layout.addView(view);

这样写的话,你就会发现布局文件R.layout.layout_menu_item中的android:layout_width=”80dp”不起作用!!也就是说View.inflate方法忽略了布局文件的宽度设置
所以猜想是 第三个参数ViewGroup root

LinearLayout layout = (LinearLayout)findViewById(R.id.container);
View view = View.inflate(this, R.layout.layout_menu_item, layout);
layout.addView(view);

上面的崩溃

改为下面成功

LinearLayout layout = (LinearLayout)findViewById(R.id.container);
View view = View.inflate(this, R.layout.layout_menu_item, layout);

View.inflate方法自动将生成的View添加到了这个ViewGroup root中去了!!

其实View.inflate方法是调用了LayoutInflater.from(context).inflate(resource, root, root != null)方法,而inflate方法的三个参数如下:

* resource: 布局文件的id,比如R.layout.layout_menu_item
* root:这是一个可选参数,resource布局文件中layout_*参数设置的参照物就是这个root,也就是说inflate方法会根据这个root的大小,将resource布局文件中layout_*参数转换成一个LayoutParam对象
* attachToRoot:是否将这个生成的View添加到这个root中去

inflate方法会返回resource布局文件产生的View

上面栗子中调用了View.inflate(Context context, int resource, ViewGroup root),这个方法本质上是调用了了LayoutInflater.from(context).inflate(resource, root, root != null), 在这个inflate方法中可以找到下面代码:

// 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);
}

可见inflate方法自动将这个生成的View添加到了这个root中去了
踩坑总结:

1. 调用LayoutInflater.inflate方法,并且将root参数设置为null,就等于忽略了xml布局文件中的layout_×参数

2. 如果root不为null,并且attachRoot=true,那么就会根据root生成一个布局文件View的LayoutParam对象,并且将这个View添加到root中去,并且返回这个root的View

3. 

因此,最好还是使用这个代码吧:View v1 = LayoutInflater.from(this).inflate(R.layout.layout_menu_item, layout, false);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值