LayoutInflater的inflate方法学习
2016-04-20 19:45
513 查看
LayoutInflater的inflate方法很常用,用于动态加载布局。inflate方法有四种调用方式:
public View inflate(int resource, ViewGroup root);
public View inflate(XmlPullParser parser, ViewGroup root);
public View inflate(int resource, ViewGroup root, boolean attachToRoot);
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot);
实质上最后都是调用第4个方法,内部原理即用XmlPullParser解析xml文件,然后返回view对象。
接下来针对我们最常用的public View inflate(int resource, ViewGroup root, boolean attachToRoot)方法进行说明。
首先,参数说明。
1. resource:布局的资源id
2. root:填充的根视图
3. attachToRoot:是否将创建的师傅绑定到根视图中
那么问题来了?
inflate(layoutId, null )
inflate(layoutId, root, false)
inflate(layoutId, root, true)
以上三种方式到底有什么区别?接下来通过一个简单的示例来说明。
首页放置一个listview。下面是list_item.xml的内容。
main_activity.java的内容如下:
区别在于getView中的布局加载方式:
①convertView = inflater.inflate(R.layout.list_item,null);
②convertView = inflater.inflate(R.layout.list_item,parent,false);
③convertView = inflater.inflate(R.layout.list_item,parent,true);
三者的运行结果分别是这样的:
方式①如图。可见list_item根布局的属性没有生效。
方式②:
方式③:
程序crash。log如下:
接下来,回到inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) 方法中看看为什么会这样。
ViewGroup.LayoutParams params = null;
从源码中可以发现,如果root为null,因为layout_width,layout_height是相对父级视图设置的,必须与父级的LayoutParams一致。而此时的getLayoutParams为null,list_item根布局的属性会被忽略掉,而使用默认的wrap_content方式。所以设置的高度被忽略。如果要使高度生效,可以将根布局的layout_height改为wrap_content, 而将textview的layout_height改为50dp。如果root不为null,attachToRoot为false,则可以正确地处理。
如果root不为null,attachToRoot为true,则会将改布局通过addview绑定到root视图里去,而此时的root是我们的ListView,ListView为AdapterView的子类,listview不支持addview方法,因此方式③就报错了。但是如果换一种场景,假设根布局是LinearLayout,用方式③是正确的,相当于在原有布局中动态加载布局。
如果root不为null,attachToRoot为true则返回root;attachToRoot为false则返回加载的view本身。
看到这里,平时在使用inflate方法时,属性不生效、或者参数到底该怎么传也就明白了。
public View inflate(int resource, ViewGroup root);
public View inflate(XmlPullParser parser, ViewGroup root);
public View inflate(int resource, ViewGroup root, boolean attachToRoot);
public View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot);
实质上最后都是调用第4个方法,内部原理即用XmlPullParser解析xml文件,然后返回view对象。
接下来针对我们最常用的public View inflate(int resource, ViewGroup root, boolean attachToRoot)方法进行说明。
首先,参数说明。
1. resource:布局的资源id
2. root:填充的根视图
3. attachToRoot:是否将创建的师傅绑定到根视图中
那么问题来了?
inflate(layoutId, null )
inflate(layoutId, root, false)
inflate(layoutId, root, true)
以上三种方式到底有什么区别?接下来通过一个简单的示例来说明。
首页放置一个listview。下面是list_item.xml的内容。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="50dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/text_tv" android:textSize="16sp" android:text="Hello world!"/> </LinearLayout>
main_activity.java的内容如下:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.content_main); ListView myListView = (ListView)findViewById(R.id.list_view); myListView.setAdapter(new MyAdapter(this)); } private class MyAdapter extends BaseAdapter { private LayoutInflater inflater; public MyAdapter(Context context) { inflater = LayoutInflater.from(context); } @Override public int getCount() { return 10; } @Override public Object getItem(int position) { return position; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if(convertView == null) { convertView = inflater.inflate(R.layout.list_item,null); } return convertView; } } }
区别在于getView中的布局加载方式:
①convertView = inflater.inflate(R.layout.list_item,null);
②convertView = inflater.inflate(R.layout.list_item,parent,false);
③convertView = inflater.inflate(R.layout.list_item,parent,true);
三者的运行结果分别是这样的:
方式①如图。可见list_item根布局的属性没有生效。
方式②:
方式③:
程序crash。log如下:
接下来,回到inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) 方法中看看为什么会这样。
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, true); 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; }
从源码中可以发现,如果root为null,因为layout_width,layout_height是相对父级视图设置的,必须与父级的LayoutParams一致。而此时的getLayoutParams为null,list_item根布局的属性会被忽略掉,而使用默认的wrap_content方式。所以设置的高度被忽略。如果要使高度生效,可以将根布局的layout_height改为wrap_content, 而将textview的layout_height改为50dp。如果root不为null,attachToRoot为false,则可以正确地处理。
如果root不为null,attachToRoot为true,则会将改布局通过addview绑定到root视图里去,而此时的root是我们的ListView,ListView为AdapterView的子类,listview不支持addview方法,因此方式③就报错了。但是如果换一种场景,假设根布局是LinearLayout,用方式③是正确的,相当于在原有布局中动态加载布局。
如果root不为null,attachToRoot为true则返回root;attachToRoot为false则返回加载的view本身。
看到这里,平时在使用inflate方法时,属性不生效、或者参数到底该怎么传也就明白了。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories