学习笔记(四)ListView
2016-04-18 22:02
513 查看
一. 最常用和最难用的控件 ListView
ListView 可以称得上是 Android 中最常用的控件之一,几乎所有的应用程序都会用到它。ListView 允许用户通过手指上下滑动的方式将屏幕外的数据滚动到屏幕内,同时屏幕上原有的数据则会滚动出屏幕。1. 最简单的适配器 ArrayAdapter
数组中的数据无法直接传递给 ListView,需要借助适配器来完成。ArrayAdapter 可以通过泛型来指定要适配的数据类型,然后在构造函数中把要适配的数据传入。ArrayAdapter 接收3个参数:context,ListView 单个子项布局 id 和数据。ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this,android.R.layout.simple_list_item_1,data); ListView listView = (ListView) findViewById(R.id.listView1); listView.setAdapter(adapter);
2. 定制 ListView 界面
(1)准备数据,Fruit 类首先要准备好需要适配的数据,包括文字、图片(id),定义一个 Fruit 类作为 ListView 适配类型。Fruit 类需要传入 name 水果的名字和 imageId 水果对应的图片的资源 id。
(2)为 ListView 子项指定布局
创建 fruit_item.xml,定义一个 ImageView 用于显示图片,定义一个 TextView 用于显示名称。
(3)自定义适配器
这个适配器继承自 ArrayAdapter ,并将泛型指定为 Fruit 类。新建类 FruitAdapter。该适配器中,最重要的是
getView()方法。该方法在每个子项滚动到屏幕内时被调用。position 是该子项的位置,利用
getItem(position)可以获得当前的 Fruit 实例 fruit;然后使用 LayoutInflater 来为子项加载步骤(2)中自定义的布局,然后通过
view.findViewById()分别获取 ImageView 和 TextView 的实例,并调用它们的
setImageResource()和
setText()设置好要显示图片和文字,最后将布局返回。
public class FruitAdapter extends ArrayAdapter<Fruit>{ private int resourceId; public FruitAdapter(Context context,int resource,List<Fruit> objects) { super(context,resource,objects); resourceId = resource; } @override public View getView(int position,View convertView,ViewGroup parent) { Fruit fruit = getItem(position);//获取当前项的Fruit实例 View view=LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout,null); TextView fruit_name = (TextView) view.findViewById(R.id.fruit_name); ImageView fruit_image = (ImageView) view.findViewById(R.id.fruit_image); fruit_image.setImageResource(fruit.getImageId()); fruit_name.setText(fruit.getName()); return view; } }
LayoutInflater 的作用是将 layout 的 xml 布局文件实例化为 View 类对象。
inflate()的作用就是将一个用 xml 定义的布局文件查找出来,注意与 findViewById() 的区别,inflate 是加载一个布局文件,而 findViewById 则是从布局文件中查找一个控件。
(4)初始化 Fruit 数据。将 fruit 中的 imageId 和 name 传入 ImageView 和 TextView。
3. 提升 ListView 的效率
(1)convertView因为
getView()方法每次都将布局重新加载一遍,效率很低。
getView()方法中还有一个 convertView 参数,这个参数用于将之前加载好的布局进行缓存,以便之后可以重用。如此一来,就可以不必每次都用 LayoutInflate 加载布局。
View view; if(convertView == null){ view=LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout,null); } else { view = convertView; }//如果convertView为空则使用LayoutInflater加载布局;不然直接对convertView进行重用
(2)ViewHolder
虽然现在不会再重复加载布局,但是每次在
getView()方法中还是会调用 View 的
findViewById()方法来获取一次控件的实例。我们可以借助一个 ViewHolder 来对控件的实例进行缓存。如此一来,就没有必要每次都通过
findViewById()来获取控件实例。
View 有
setTag()和
getTag()方法,分别进行数据写入和读取。
public class FruitAdapter extends ArrayAdapter<Fruit> { private int resourceId; public FruitAdapter(Context context,int resource,List<Fruit> objects) { super(context,resource,objects); resourceId = resource; } public View getView(int position,View convertView,ViewGroup parent) { Fruit fruit = getItem(position); View view; ViewHolder viewHolder; if (convertView == null) { viewHolder = new ViewHolder(); //一定要记住实例化对象啊 view = LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout, null); viewHolder.fruit_image = (ImageView) view.findViewById(R.id.fruit_image); viewHolder.fruit_name = (TextView) view.findViewById(R.id.fruit_name); view.setTag(viewHolder);//将ViewHolder存储在View中 } else { view = convertView; viewHolder = (ViewHolder) view.getTag();//重新获取ViewHolder } viewHolder.fruit_image.setImageResource(fruit.getImageId()); viewHolder.fruit_name.setText(fruit.getName()); return view; } class ViewHolder { //新增一个内部类ViewHolder用于对控件的实例进行缓存 ImageView fruit_image; TextView fruit_name; } }
4000
通过这两步的优化后,我们 ListView 的运行效率就已经非常不错了。
4. ListView的点击事件
注册setOnItemClickListener()事件:
listView.setOnItemClickListener(new OnItemClickListener() { @override public void onItemClick(AdapterView<?> parent,View view,int position, long id) { Fruit fruit=fruits.get(position); Toast.makeText(MainActivity.this, fruit.getName(),Toast.LENGTH_SHORT).show(); } });
二. 单位和尺寸
1. dp (density-independent pixels)
dp 是密度无关像素的意思,也被称作 dip,和 px 相比,它在不同密度的屏幕中的显示比例将保持一致。2. sp (scale-independent pixels)
sp 是可伸缩像素的意思,它采用了和 dp 同样的设计理念,解决了文字大小的适配问题。3. 密度
什么是密度? Android 中的密度就是屏幕每英寸所包含的像素数,通常以 dpi 为单位。密度值越高的屏幕显示的效果就越精细。获取当前屏幕密度值:
float xdpi = getResources().getDisplayMetrics().xdpi; float ydpi = getResources().getDisplayMetrics().ydpi;
三. 最佳实践——聊天界面
新内容有:当有新内容时,刷新 ListView 中的显示:
adapter.notifyDataSetChanged();
将 ListView 显示的数据定位到最后一行:
listView.setSelection(messages.size());
指定 ListView 中分割线为透明:
android:divider="#0000"
相关文章推荐
- 使用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