您的位置:首页 > 编程语言

第一行代码3.5-最常用和最难用的控件--ListView

2016-02-04 15:31 288 查看
  首先这个控件为什么是最常用的呢?因为手机屏幕大小有限,有些东西比如新闻、手机联系人微博等大量数据不可能全部显示出来,需要通过滑动手机屏幕翻阅信息。这种方法用到的控件就是ListView

1、ListView的简单用法

  首先创建一个工程名为ListViewTest,然后在activity_main.xml中添加如下代码:



  然后在MainActivity.java中添加:



  其中adapter的作用是设置ListView的布局和数据,第一个参数是context,第二个参数是Android自带的布局,第三个参数是数据。如果是微博,那么这个数据就来自网络,通讯录就来自本地。

  效果如下:



2、定制ListView的界面

  之前的界面太单调了,下面介绍怎么显示图片+文字。

  首先创建一个水果类,命名为Fruit:

package com.example.listviewtest;

public class Fruit {

private String name; // 水果名
private int imageId; // 水果图片id

public Fruit(String name, int imageId) {
this.name = name;
this.imageId = imageId;
}

public String getName() {
return name;
}

public int getImageId() {
return imageId;
}
}


  然后创建显示水果类的布局fruit_item.xml:左边水果图片,右边水果名

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >

<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:id="@+id/textView"
android:layout_marginLeft="10dp"/>

</LinearLayout>


  注意一些宽度和距离的设置。

  由于这个布局中显示的内容包括图片和文字,所以需要自定义适配器来显示:

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 item = getItem(position);

View view = LayoutInflater.from(getContext()).inflate(resourceId, null);
TextView tv = (TextView) view.findViewById(R.id.textView);
ImageView iv = (ImageView) view.findViewById(R.id.imageView);
tv.setText(item.getName());
iv.setImageResource(item.getImageId());

return view;
}

}


  其中getView函数在每一个子项被滚动到屏幕中显示的时候会被调用。在getView 方法中,首先通过getItem()方法得到当前项的Fruit 实例,然后使用LayoutInflater 来为这个子项加载我们传入的布局,接着调用View 的findViewById()方法分别获取到ImageView 和TextView 的实例,并分别调用它们的setImageResource()和setText()方法来设置显示的图片和文字,最后将布局返回,这样我们自定义的适配器就完成了。

  最后修改MainActivity的代码:



  这样水果的数据和界面都加载完成了。效果如下:



3、提升ListView运行效率

  之前说到ListView难用,原因之一就是有很多地方可以优化,其中一个地方就是修改getView函数:getView每次都会把布局重新加载一遍,所以当ListView快速滚动的时候,性能会产生瓶颈。

  getView中还有一个convertView参数,它就是之前加载的布局的缓存,所以可以这样得到view:

View view;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(resourceId, null);
}
else view = convertView;


  这样在快速滚动ListView的时候效率会有所提升。但是还可以优化,因为每次还是要通过findViewById才能获取控件的实例,所以可以用一个ViewHolder来保存控件,如下:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

final Fruit item = getItem(position);

View view;
ViewHolder viewHolder;
if (convertView == null) {
view = LayoutInflater.from(getContext()).inflate(resourceId, null);
viewHolder = new ViewHolder();
viewHolder.imageView = (ImageView) view.findViewById(R.id.imageView);
viewHolder.textView = (TextView) view.findViewById(R.id.textView);
view.setTag(viewHolder); // 将viewHolder存储到View中
}
else {
view = convertView;
viewHolder = (ViewHolder)view.getTag(); // 重新获取ViewHolder
}
viewHolder.textView.setText(item.getName());
viewHolder.imageView.setImageResource(item.getImageId());

return view;
}


  当view是新加载的时候,会把TextView和ImageView赋值给ViewHolder,并且附到View的TAG中,当读取缓存的时候再从View中获取回来。

4、ListView的点击事件

  如果ListView没有点击事件,那也是没什么作用的,所以需要设置每一项的点击事件。注意不是OnClickListener,而是OnItemClickListener。

listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {

@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
Fruit fruit = fruitList.get(position);
Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_SHORT).show();
}
});


  下面说说这四个参数是什么意思(来自20110921 onItemClick监听器四个arg参数):首先AdapterView表示你现在点击的ListView是哪个,通过View可以获取ListView里面某一项的内容(比如可以获取某一个水果的TextView或者ImageView),position表示点击的item在适配器里的位置,id表示点击的item是listview的第几行,在大部分情况下id和position是相同的。

  下面验证通过position获取的水果名和通过view获取的是一样的:

TextView fruitText = (TextView) view.findViewById(R.id.textView);
Toast.makeText(MainActivity.this, fruitText.getText().toString()+" "+fruit.getName(), Toast.LENGTH_SHORT).show(); // 输出两者相同


  下面是自己另外加的内容:设置长按删除点击事件。长按删除包括在list中删除对应水果和更新适配器。

listview.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

@Override
public boolean onItemLongClick(AdapterView<?> adapterView, View view, int position, long id) {
fruitList.remove(position); // 删除对应水果
adapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item, fruitList); // 更新适配器
listview.setAdapter(adapter);
return true;
}
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: