您的位置:首页 > 其它

关于LayoutInflater

2012-08-26 11:35 435 查看

一、如何获得 LayoutInflater 实例

LayoutInflater作用是将layout的xml布局文件实例化为View类对象。

实现LayoutInflater的实例化共有3种方法,

(1).通过SystemService获得

LayoutInflaterinflater = (LayoutInflater)context.getSystemServices(Context.LAYOUT_INFLATER_SERVICES);
Viewview = inflater.inflate(R.layout.main, null);
(2).从给定的context中获得

LayoutInflaterinflater = LayoutInflater.from(context);
Viewview = inflater.inflate(R.layout.mian, null);
(3).

LayoutInflaterinflater =getLayoutInflater();(在Activity中可以使用,实际上是View子类下window的一个函数)
Viewlayout = inflater.inflate(R.layout.main, null);


其实,这三种方式本质是相同的,从源码中可以看出:

getLayoutInflater():

Activity的getLayoutInflater()方法是调用PhoneWindow的getLayoutInflater()方法,看一下该源代码:

public PhoneWindow(Contextcontext) {
super(context);
mLayoutInflater= LayoutInflater.from(context);
}
可以看出它其实是调用LayoutInflater.from(context)。

LayoutInflater.from(context):

public static LayoutInflaterfrom(Context context) {
LayoutInflaterLayoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(LayoutInflater== null){
thrownew AssertionError("LayoutInflaternot found.");
}
returnLayoutInflater;
}
可以看出它其实调用context.getSystemService()。

二、LayoutInflater的inflate 方法

inflate 愿意是充气之类的,在这里主要意思就是,扩张、使之膨胀。

换句话说就是将当前视图view 补充完整、扩展该视图。

public View inflate(int Resourece,View Grouproot)

作用:填充一个新的视图层次结构从指定的XML资源文件中

reSource:View的layout的,也就是resource/layout文件在R文件中对应的ID,这个必须指定。

root: 生成的层次结构的根视图,可以是null,null时就只创建一个resource对应的View,不是null时,会将创建的view自动加为root的child。

return 填充的层次结构的根视图。如果参数root提供了,那么root就是根视图;否则填充的XML文件的根就是根视图。

其余几个重载的inflate函数类似。

通过 sdk 的 api 文档,可以知道该方法有以下几种过载形式,返回值均是 View 对象,如下:
public View inflate (int resource, ViewGroup root)
public View inflate (XmlPullParser parser, ViewGroup root)
public View inflate (XmlPullParser parser, ViewGroup root, boolean attachToRoot)
public View inflate (int resource, ViewGroup root, boolean attachToRoot)

示例代码:

LayoutInflater inflater = (LayoutInflater)
getSystemService(LAYOUT_INFLATER_SERVICE);

/* R.id.test 是 custom.xml 中根(root)布局 LinearLayout 的 id */
View view = inflater.inflate(R.layout.custom,
(ViewGroup)findViewById(R.id.test));

/* 通过该 view 实例化 EditText对象, 否则报错,因为当前视图不是custom.xml.

即没有 setContentView(R.layout.custom) 或者 addView() */

//EditText editText = (EditText)findViewById(R.id.content);// error
EditText editText = (EditText)view.findViewById(R.id.content);


对于上面代码,指定了第二个参数 ViewGroup root,当然你也可以设置为 null 值。

注意:该方法与 findViewById 方法不同。

inflater 是用来找 layout 下 xml 布局文件,并且实例化!

而 findViewById() 是找具体 xml 下的具体 widget 控件(如: Button,TextView 等)。

三、setContentView(int id)与LayoutInflater.inflate的关系

然后再看一下 PhoneWindow源码,我们可以看到

@Override
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);
final Callback cb = getCallback();
if (cb != null) {
cb.onContentChanged();
}
}

setContentView其实是调用了LayoutInflater.inflate方法。

说明其实在Activity里,通过getSystemService(Context.LAYOUT_INFLATER_SERVICE)方法可以获得一个 LayoutInflater, 然后使用inflate方法来载入layout的xml,然后在展现在用户面前。

四、因为要动态加载View而而造成的两种findViewById

第一种. Activity中的findViewById(int id)

R.layout.xx是引用res/layout/xx.xml的布局文件(inflate 方法),R.id.xx是引用布局文件里面的组件,组件的id是xx(findViewById方法)。所有的组件id都能用R.id.xx来查看,但是组件不在setContentView()里面的layout中就无法使用,Activity.findViewById()会出现空指针异常,也就是说当你使用Activity.findViewById()时,这个组件必须是当初在setContentView()加载时所加载的布局文件当中的一个组件。如果不是就会出现空指针异常。

第二种. View 中的findViewById(int id)

对于第二种情况,我们会经常在自定义ListView的Adapter时使用到。
convertView = View.inflate(mContext, R.layout.listview_item, null);
holder = new ViewHolder();
holder.no = (TextView) convertView.findViewById(R.id.no);
holder.click = (TextView) convertView.findViewById(R.id.click);

View.inflate的源码
/**
* Inflate a view from an XML resource.  This convenience method wraps the {@link
* LayoutInflater} class, which provides a full range of options for view inflation.
*
* @param context The Context object for your activity or application.
* @param resource The resource ID to inflate
* @param root A view group that will be the parent.  Used to properly inflate the
* layout_* parameters.
* @see LayoutInflater
*/
public static View inflate(Context context, int resource, ViewGroup root) {
LayoutInflater factory = LayoutInflater.from(context);
return factory.inflate(resource, root);
}
可以看到其调用了 factory.inflate(resource, root);得到了一个View,而这个View与我们在Activity的onCtreate方法当中调用setContentView时产生的View是类似的,只不过setContentView中的View是皇后,而这里的View是妃子,皇后是必须需要的,而妃子却是根据实际情况可有可无,是动态加载的。
同时因为皇后的权利大,因此在调用findViewById时,可以不用显示的指出view,默认的就是this。而妃子权利相对较小,因此要指出是皇帝调用的,要显示指出,因此出现了View.findViewById得到刚开始View.inflate得到布局文件当中的组件。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: