ListView可以说是我们在进行Android开发时候最常见的控件之一了,那么我们该如何使用呢?这里主要介绍两种方法。

  1. 使用Activity(继承自AppCompactActivity)+ListView控件
  2. 使用Activity(继承自ListActivity)

继承自AppCompactActivity


首先,让我们来看看第一种方法。用一个小例子来介绍一下。

Step1:新建一个工程,修改activity_main.xml的代码如下

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.xkw.listviewtest.MainActivity">

    <ListView
        android:id="@+id/listview_fruit"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>

在这里我们只添加了一个ListView的控件,并没有添加其它的东西。

Step2:如图,layout右键->new->Layout Source File,新建一个listitem.xml文件。这个listitem就是listview里面的每一个小单元要显示的东西,这里我们只显示一个字符串就只添加一个TextView控件就行。

这里写图片描述

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

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="match_parent"
        android:layout_height="51dp"
        android:textSize="24sp" />
</android.support.constraint.ConstraintLayout>

Step3:在MainActivity里面修改代码如下

package com.example.xkw.listviewtest;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    //自己定义的一组用于显示的数据
    private String[] fruit =
{"苹果","香蕉","橙子","西瓜","梨","葡萄","菠萝","草莓","芒果","蔓越莓",
"榴莲","山竹","柚子","哈密瓜","水蜜桃","番石榴","黄桃","蛇果","蜜瓜","蓝莓","甘蔗"};
    private FruitAdapter mfruitAdapter;
    private ListView mlistView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mlistView = (ListView)findViewById(R.id.listview_fruit);
        mfruitAdapter = new FruitAdapter();
        initFruits();
        mlistView.setAdapter(mfruitAdapter);
        mlistView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(MainActivity.this,"您选择了:" + ((Fruit) mfruitAdapter.getItem(i)).getName(),Toast.LENGTH_SHORT).show();
            }
        });
    }
    private void initFruits(){
        for (int i = 0;i < fruit.length;i ++){
            Fruit newfruit = new Fruit(fruit[i]);
            mfruitAdapter.addFruit(newfruit);
        }
    }

    public class Fruit{
        //定义了一个水果类
        private String Name;
        //private int ImageId; //用于存放水果图片的Id,此处没有
        public Fruit(String name){
            this.Name = name;
        }

        public String getName(){
            return Name;
        }
    }

    private class FruitAdapter extends BaseAdapter{
        private ArrayList<Fruit> mFruit;
        private LayoutInflater mInflator;

        public FruitAdapter(){
            super();
            mFruit = new ArrayList<Fruit>();
            mInflator = MainActivity.this.getLayoutInflater();
        }

        public void addFruit(Fruit fruit){
            mFruit.add(fruit);
        }
        @Override
        public int getCount() {
            return mFruit.size();
        }

        @Override
        public Object getItem(int i) {
            return mFruit.get(i);
        }

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

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            ViewHolder viewHolder;
            //常规ListView优化代码
            if (view == null){
                //注意inflate()的第三个参数必须设置为false,不然会和onCreate函数里面的setContentView冲突
                view = mInflator.inflate(R.layout.listitem,null,false);
                viewHolder = new ViewHolder();
                viewHolder.fruitName = (TextView)view.findViewById(R.id.fruit_name);
                view.setTag(viewHolder);//将ViewHolder储存至view内
            }
            else {
                viewHolder = (ViewHolder)view.getTag();//从view内读取ViewHolder
            }
            Fruit fruit = mFruit.get(i);
            viewHolder.fruitName.setText(fruit.getName());
            return view;
        }
        class ViewHolder{
            //定义了一个内部类ViewHolder用于对每一个水果的信息进行缓存
            TextView fruitName;
        }
    }
}

  下面我们来详细分析一下这段代码。

  首先先解释一下定义的几个类:

  首先,自己预先定义一些用于显示的数据。

private String[] fruit =
{"苹果","香蕉","橙子","西瓜","梨","葡萄","菠萝","草莓","芒果","蔓越莓",
 "榴莲","山竹","柚子","哈密瓜","水蜜桃","番石榴","黄桃","蛇果","蜜瓜","蓝莓","甘蔗"};

   然后,在onCreate()函数里面绑定ListView控件并设定相应的Adapter即可(Adapter是数据(Data)和界面(UI)之间的桥梁)。总的来说,只需要一下这么几步:绑定控件->添加数据->设定Adapter,就可以实现ListView的显示功能了。

setContentView(R.layout.activity_main);//加载布局文件
mlistView = (ListView)findViewById(R.id.listview_fruit);//绑定控件
mfruitAdapter = new FruitAdapter();//新建一个Adapter
initFruits();//添加数据
mlistView.setAdapter(mfruitAdapter);//设定Adapter

  这么几行代码就已经可以完成显示的功能了,话不多说,直接来看看实际效果图。

这里写图片描述

  但是假如一个ListView只有显示的功能未免太过鸡肋,那么就让我们来添加一下点击处理函数。其实很简单,只需要直接调用listview的setOnItemClickListener()函数即可(参数i就是点击的单元的序号)。如下,我们在里面通过Toast显示用户点击了哪一个水果。

mlistView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Toast.makeText(MainActivity.this,"您选择了:" + ((Fruit) mfruitAdapter.getItem(i)).getName(),Toast.LENGTH_SHORT).show();
            }
        });

这里写图片描述

  至此为止,一个完整的ListView就已经实现了。以上就是介绍的第一种实现ListView的方法。

继承自ListActivity


  下面介绍第二种实现ListView的方法,就是让这个类继承自ListActivity。

public class MainActivity extends ListActivity {
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
    }
}

  然后其他的就和第一种用法差不多了,同样的新建Fruit和FruitAdapter,ViewHolder三个类。需要注意的是,ListActivity是没有布局文件的!!!但是Android Studio默认生成的是继承自AppCompactActivity的活动,在onCreate()函数里面会加载布局文件,所以假如创建的时候没有注意勾选不要布局文件的话一定要注意把onCreate()函数里面的setContentView(R.layout.activity_main);这句话注释掉!!!不然运行会报错。

  介绍一下使用ListActivity相较于第一种方法的几个细微之处。

  1. ListActivity本身已经定义了点击函数,我们需要做的只是重载一下就好了。
protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        Toast.makeText(MainActivity.this,"您选择了:" + ((Fruit) mfruitAdapter.getItem(position)).getName(),Toast.LENGTH_SHORT).show();
    }
  1. 同样绑定Adapter的函数ListActivity也已经帮我们做好了,我们只需要直接调用就好了。
setListAdapter(mfruitAdapter);

  程序运行之后,可以看到与第一种效果一模一样,具体图在这里就不贴了。

源码下载


  ListView的两种实现方法就介绍到这里了。理论上来说用哪种方法都是可以的,看你喜欢用哪种而已。但是个人比较推荐第一种方法,使用listview控件,不要继承于ListActivity。因为继承自ListActivity的话是没有布局文件的,能修改的只有默认的ActionBar,但是Google现在已经推出了Material Design,而ActionBar也被更灵活的ToolBar所取代,越来越多的应用也开始采用ToolBar的设计方式,但是使用ToolBar需要自己定义布局文件,与ListActivity不能使用布局文件是矛盾的,所以更建议大家使用listview控件。以上纯属个人之愚见,欢迎有不同意见的评论交流。