LayoutInflater三种模式的差别
2015-09-06 15:15
239 查看
LayoutInflater有三种加载方法,分别是inflate(layoutId, null ),inflate(layoutId,
root, false ) ,inflate(layoutId, root, true ).对于这三种方法加载有什么区别呢?下面我们用一个listview去看一下,新建一个listview,里面只有一个button:
Activity的布局文件:<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/id_listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>
Listview的Item文件:
主Activity:
我们主要关注getView里面的inflate那行代码:下面我依次把getView里的写成:
1、convertView = mInflater.inflate(R.layout.item, null);
2、convertView = mInflater.inflate(R.layout.item, parent ,false);
3、convertView = mInflater.inflate(R.layout.item, parent ,true);
第一个方法加载后,我们会发现listView中的item设置的宽高无效,显示的item为wrap_content的
第二个方法加载后,我们会发现listView中的item设置的宽高得到了正确的执行,显示的item为我们设置的宽高
第三个方法加载后,会报“addView(View)
is not supported in AdapterView”错误。
然后观察源码我们会发现:
对于第一种加载方法,没有为其设置相应于父布局的layoutParams所以无法显示正常的宽高
对于第二种加载方法,为其设置了相应于父布局的layoutParams,所以可以正常显示item制定的宽高
对于第三种加载方法,会调用root.addview()方法,而adapterview是不支持addview()的,所以会抛出异常
那么为什么设置layoutParams就无法显示正常的宽高呢?我们从viewgroup和view的onmeasure()方法解析:
ViewGroup的onMeasure方法所做的是:
为childView设置测量模式和测量出来的值。
如何设置呢?就是根据LayoutParams。
如果childView的宽为:LayoutParams. MATCH_PARENT,则设置模式为MeasureSpec.EXACTLY,且为childView计算宽度如果childView的宽为:固定值(即大于0),则设置模式为MeasureSpec.EXACTLY,且将lp.width直接作为childView的宽度如果childView的宽为:LayoutParams.
WRAP_CONTENT,则设置模式为:MeasureSpec.AT_MOST
View的onMeasure方法:
主要做的就是根据ViewGroup传入的测量模式和测量值,计算自己应该的宽和高:
一般是这样的流程:
如果宽的模式是AT_MOST:则自己计算宽的值。
如果宽的模式是EXACTLY:则直接使用MeasureSpec.getSize(widthMeasureSpec);
root, false ) ,inflate(layoutId, root, true ).对于这三种方法加载有什么区别呢?下面我们用一个listview去看一下,新建一个listview,里面只有一个button:
Activity的布局文件:<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/id_listview"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>
Listview的Item文件:
<Button xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/id_btn" android:layout_width="120dp" android:layout_height="120dp" > </Button>Listview的适配器:
<pre name="code" class="java">public class MyAdapter extends BaseAdapter { private LayoutInflater mInflater; private List<String> mDatas; public MyAdapter(Context context, List<String> datas) { mInflater = LayoutInflater.from(context); mDatas = datas; } @Override public int getCount() { return mDatas.size(); } @Override public Object getItem(int position) { return mDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.item, null); // convertView = mInflater.inflate(R.layout.item, parent ,false); // convertView = mInflater.inflate(R.layout.item, parent ,true); holder.mBtn = (Button) convertView.findViewById(R.id.id_btn); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.mBtn.setText(mDatas.get(position)); return convertView; } private final class ViewHolder { Button mBtn; } }
主Activity:
import android.app.Activity; import android.os.Bundle; import android.widget.ListView; public class MainActivity extends Activity { private ListView mListView; private MyAdapter mAdapter; private List<String> mDatas = Arrays.asList("Hello", "Java", "Android"); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mListView = (ListView) findViewById(R.id.id_listview); mAdapter = new MyAdapter(this, mDatas); mListView.setAdapter(mAdapter); } }
我们主要关注getView里面的inflate那行代码:下面我依次把getView里的写成:
1、convertView = mInflater.inflate(R.layout.item, null);
2、convertView = mInflater.inflate(R.layout.item, parent ,false);
3、convertView = mInflater.inflate(R.layout.item, parent ,true);
第一个方法加载后,我们会发现listView中的item设置的宽高无效,显示的item为wrap_content的
第二个方法加载后,我们会发现listView中的item设置的宽高得到了正确的执行,显示的item为我们设置的宽高
第三个方法加载后,会报“addView(View)
is not supported in AdapterView”错误。
然后观察源码我们会发现:
对于第一种加载方法,没有为其设置相应于父布局的layoutParams所以无法显示正常的宽高
对于第二种加载方法,为其设置了相应于父布局的layoutParams,所以可以正常显示item制定的宽高
对于第三种加载方法,会调用root.addview()方法,而adapterview是不支持addview()的,所以会抛出异常
那么为什么设置layoutParams就无法显示正常的宽高呢?我们从viewgroup和view的onmeasure()方法解析:
ViewGroup的onMeasure方法所做的是:
为childView设置测量模式和测量出来的值。
如何设置呢?就是根据LayoutParams。
如果childView的宽为:LayoutParams. MATCH_PARENT,则设置模式为MeasureSpec.EXACTLY,且为childView计算宽度如果childView的宽为:固定值(即大于0),则设置模式为MeasureSpec.EXACTLY,且将lp.width直接作为childView的宽度如果childView的宽为:LayoutParams.
WRAP_CONTENT,则设置模式为:MeasureSpec.AT_MOST
View的onMeasure方法:
主要做的就是根据ViewGroup传入的测量模式和测量值,计算自己应该的宽和高:
一般是这样的流程:
如果宽的模式是AT_MOST:则自己计算宽的值。
如果宽的模式是EXACTLY:则直接使用MeasureSpec.getSize(widthMeasureSpec);
相关文章推荐
- 使用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