您的位置:首页 > 移动开发 > Android开发

学习笔记(四)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"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android 学习笔记