Android - ListView

ListView是Android软件开发中非常重要组件之一,基本上是个软件基本都会使用ListView。ListView用于显示大量相同格式数据。

常用方法:
    setAdapter() 设置数据适配器
    setOnItemClickListener() 设置每项点击事件监听
    
Adapter数据适配器 将各种数据以合适的形式绑定到控件上 像listview, gridview, spinner 等等等控件 都会用到Adapter绑定数据。
介绍三种Adapter

  • ArrayAdapter:支持泛型操作,最简单的一个Adapter
  • SimpleAdapter:同样具有良好扩展性的一个Adapter,可以自定义多种效果
  • BaseAdapter:抽象类,实际开发中我们会继承这个类并且重写相关方法,用得最多的一个Adapter

ArrayAdapter

简单的ListView

在List列表中如果不存在过于复杂的东西 我们可以直接去new ArrayAdapter() 来绘制列表,无须继承ArrayAdapter,重写它的方法。但是如果列表中过于复杂的话就需要使用自定义布局来实现List列表。

private String[] data = { "Apple", "Banana", "Orange", "Watermelon", "Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango" };
ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, data);
ListView listView = (ListView) findViewById(R.id.list_view); 
listView.setAdapter(adapter);

ArrayAdapter 的构造函数中依次传入当前上下文、ListView 子项布局的 id,以及要适配的数据。注意我们使用了 android.R.layout.simple_list_item_1 作为 ListView 子项布局的 id,这是一个 Android 内置的布 局文件,里面只有一个 TextView,可用于简单地显示一段文本。这样适配器对象就构建好了。最后,还需要调用 ListView 的 setAdapter()方法,将构建好的适配器对象传递进去,这 样 ListView 和数据之间的关联就建立完成了。

自定义布局ArrayAdapter

ArrayAdapter是BaseAdapter的子类,ArrayAdapter不仅具有BaseAdapter的所有方法还自定义了一些新的方法来处理列表项,所以单纯的从功能能上来讲ArrayAdapter远远强与BaseAdapter,如果是绘制一些数量比较少的列表建议使用BaseAdapter 如果绘制一些比较复杂的列表项 并且列表项很多的 建议使用ArrayAdapter。

定义一个实体类,作为 ListView 适配器的适配类型。新建类 Fruit。

public class Fruit {
    private String name;
    private int imageId;
    public Fruit(String name, int imageId) {
        this.name = name;
        this.imageId = imageId;
    } 
    public String getName() {
        return name;
    }
        public int getImageId() {
            return imageId;
    } 
}

为 ListView 的子项指定一个我们自定义的布局。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <ImageView
            android:id="@+id/fruit_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/fruit_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="10dip" />
    </LinearLayout>

创建一个自定义的适配器,这个适配器继承自 ArrayAdapter,并将泛型指定 为 Fruit 类。

public class FruitAdapter extends ArrayAdapter<Fruit> {
    private int resourceId;
    public FruitAdapter(Context context, int textViewResourceId,List<Fruit> objects) {
        super(context, textViewResourceId, objects);
        resourceId = textViewResourceId;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Fruit fruit = getItem(position); // 获取当前项的Fruit实例
        View view = LayoutInflater.from(getContext()).inflate(resourceId, null); 
        ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image); 
        TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
        fruitImage.setImageResource(fruit.getImageId());
        fruitName.setText(fruit.getName());
        return view;
    } 
}

FruitAdapter 重写了父类的一组构造函数,用于将上下文、ListView 子项布局的 id 和数 据都传递进来。另外又重写了 getView()方法,这个方法在每个子项被滚动到屏幕内的时候 会被调用。在 getView 方法中,首先通过 getItem()方法得到当前项的 Fruit 实例,然后使用 LayoutInflater 来为这个子项加载我们传入的布局,接着调用 View 的 findViewById()方法分别 获取到 ImageView 和 TextView 的实例,并分别调用它们的 setImageResource()和 setText()方 法来设置显示的图片和文字,最后将布局返回。

提升 ListView 的运行效率

getView() 方法中每次都将布局重新加载了一遍,当 ListView 快速滚动的时候这就会成为性能的瓶颈。getView()方法中还有一个 convertView 参数,这个参数用于将之前加载好的 布局进行缓存,以便之后可以进行重用。我们在 getView()方法中进行了判断,如果 convertView 为空,则使用 LayoutInflater 去加载布局,如果不为空则直接对 convertView 进行重用。
新增了一个内部类 ViewHolder,用于对控件的实例进行缓存。当 convertView 为空 的时候,创建一个 ViewHolder 对象,并将控件的实例都存放在 ViewHolder 里,然后调用 View 的 setTag()方法,将 ViewHolder 对象存储在 View 中。当 convertView 不为空的时候则调用 View 的 getTag()方法,把 ViewHolder 重新取出。这样所有控件的实例都缓存在了 ViewHolder 里,就没有必要每次都通过 findViewById()方法来获取控件实例了。
总之在getView()这个方法中尽可能少创建view。

public class FruitAdapter extends ArrayAdapter<Fruit> {
......
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Fruit fruit = getItem(position);
        View view;
        ViewHolder viewHolder;
        if (convertView == null) {
            view = LayoutInflater.from(getContext()).inflate(resourceId, null); 
            viewHolder = new ViewHolder();
            viewHolder.fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            viewHolder.fruitName = (TextView) view.findViewById(R.id.fruit_name);
            view.setTag(viewHolder); // 将ViewHolder存储在View中
        } else {
            view = convertView;
            viewHolder = (ViewHolder)view.getTag(); // 重新获取ViewHolder
        }
        viewHolder.fruitImage.setImageResource(fruit.getImageId());
        viewHolder.fruitName.setText(fruit.getName());
        return view;
    }

    class ViewHolder {
        ImageView fruitImage;
        TextView fruitName;
    } 
}

SimpleAdapter

使用 simpleAdapter 需要注意的是须要用Map

public class TitleList extends ListActivity {
    private String[] mListTitle = { "姓名", "性别", "年龄", "居住地","邮箱"};
    private String[] mListStr = { "雨松MOMO", "男", "25", "北京",
        "xuanyusong@gmail.com" };
    ListView mListView = null;
    ArrayList<Map<String,Object>> mData= new ArrayList<Map<String,Object>>();;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    mListView = getListView();

    int lengh = mListTitle.length;
    for(int i =0; i < lengh; i++) {
        Map<String,Object> item = new HashMap<String,Object>();
        item.put("title", mListTitle[i]);
        item.put("text", mListStr[i]);
        mData.add(item);
    }
    SimpleAdapter adapter = new SimpleAdapter(this,mData,android.R.layout.simple_list_item_2,
        new String[]{"title","text"},new int[]{android.R.id.text1,android.R.id.text2});
        setListAdapter(adapter);
    mListView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int position,
            long id) {
        Toast.makeText(TitleList.this,"您选择了标题:" + mListTitle[position] + "内容:"+mListStr[position], Toast.LENGTH_LONG).show();
        }
    });
    super.onCreate(savedInstanceState);
    }
}

BaseAdapter

BaseAdapter是开发中最常用的适配器ArrayAdapter, SimpleAdapter 都继承于BaseAdapter。BaseAdapter可以完成自己定义的Adapter,可以将任何复杂组合的数据和资源,以任何你想要的显示效果展示给大家。
继承BaseAdapter之后,需要重写以下四个方法:getCount,getItem,getItemId,getView。

系统在绘制ListView之前,将会先调用getCount方法来获取Item的个数。每绘制一个Item就会调用一次getView方法,在getView中引用事先定义好的layout布局确定显示的效果并返回一个View对象作为一个Item显示出来。

这两个方法是自定ListView显示效果中最为重要的,同时只要重写好了这两个方法,ListView就能完全按开发者的要求显示。而getItem和getItemId方法将会在调用ListView的响应方法的时候被调用到。

student学生类

public class Stduent {
    public int imageId;
    public int  number;
    public String name;
}

StudentAdapter

public class StudentAdapter extends BaseAdapter {
    private List<Stduent> stduentList;
    private int resourceId;
    private Context context;
    public StudentAdapter(Context context, int resourceId, List<Stduent> stduentList)
    {
        this.context = context;
        this.resourceId = resourceId;
        this.stduentList = stduentList;
    }

    @Override
    public int getCount() {
        return stduentList == null? 0 : stduentList.size();
    }

    @Override
    public Object getItem(int position) {
        return stduentList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Stduent stduent = (Stduent)getItem(position);
        View view;
        ViewHolder viewHolder;
        if(convertView == null){
            view = LayoutInflater.from(context).inflate(resourceId,null);
            viewHolder = new ViewHolder();
            viewHolder.name =(TextView) view.findViewById(R.id.name);
            viewHolder.number =(TextView)  view.findViewById(R.id.number);
            viewHolder.photo = (ImageView) view.findViewById(R.id.photo);
            view.setTag(viewHolder);

        }
        else {
            view = convertView;
            viewHolder = (ViewHolder)view.getTag();
        }
        viewHolder.name.setText(stduent.name);
        viewHolder.number.setText(Integer.toString(stduent.number));
        viewHolder.photo.setImageResource(stduent.imageId);
        return view;
    }

    public class ViewHolder{
        TextView number;
        TextView name;
        ImageView photo;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值