【Android入门到项目实战--3.4】—— ListView控件的使用

目录

一、ListView的简单用法

二、进一步优化ListView界面

三、提升ListView的效率(优化)

四、ListView的点击事件


本篇文章主要讲解最常用的控件之一:ListView的使用。

        当我们的程序有大量的数据需要展示的时候,可以借助ListView实现。ListView允许用户上下滑动滚动屏幕,如:查看QQ聊天记录。

一、ListView的简单用法

 首先新建一个新的活动,csdn7.xml中的代码如下:

        布局中引入ListView控件和前面其他控件用法一致。

<?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">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

csdn7.java代码如下:

        首先准备好一个数据数组用来展示,通过适配器将数据传给ListView,ArrayAdapter的构造函数中依次传入上下文、ListView子项布局的id,要适配的数据。注意:这里使用的android.R.layout.simple_list_item_1为Android内置的布局文件,里面只有一个TextView,用于简单显示一段文本。最后调用ListView的setAdapter()方法,将适配器对象传进去,这样ListView和数据之间的关联就建立完成。

public class csdn7 extends AppCompatActivity {

    private String[] data = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N"};
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_csdn7);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                csdn7.this, android.R.layout.simple_list_item_1, data);
        ListView listView = findViewById(R.id.list_view);
        listView.setAdapter(adapter);
    }
}

效果如下:

二、进一步优化ListView界面

        只显示一段文本的ListView很单调,下面对ListView界面添加图片进行美观。效果如下:

 

新建一个Image类,作为ListView适配器的适配类型,代码如下:

        name表示每行字母的名字,imageId表示图片id。

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

 接下来需要为ListView子项指定自定义的布局,在layout目录下新建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="wrap_content">
    
    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    
    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"/>

</LinearLayout>

接下来创建一个自定义的适配器adapter类,,代码如下:

        adapter重写了父类的构造函数,用于将上下文,ListView子项布局的id和数据传递进来。

        重写getView()方法,此方法在每个子项被滚动到屏幕内时调用。

        在getView()方法中,首先通过getItem方法得到当前项的image实例,然后使用LayoutInflater方法来为这个子项加载传入的布局,LayoutInflater方法的inflate方法接收3个参数,第三个参数指定为false,表示只让在父布局中声明的layout属性生效,接下来获取到两个实例,并分别调用setImageResource和setText方法设置显示的图片和文字,最后将布局返回,这样自定义的适配器就完成了。

public class adapter extends ArrayAdapter<Image> {
    private int resourceId;
    public adapter(Context context, int textViewResourceId, List<Image> objects){
        super(context,textViewResourceId,objects);
        resourceId = textViewResourceId;
    }
    
    @Override
    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        Image image = getItem(position);
        View view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
        ImageView image2 = view.findViewById(R.id.image);
        TextView name = view.findViewById(R.id.name);
        image2.setImageResource(image.getImageId());
        name.setText(image.getImageId());
        return view;
    }
}

下面修改主类csdn7.java的代码如下:

        首先,自定义一个init()方法初始化list中的元素,然后创建自定义适配器adapter的实例,最后将适配器传递给ListView,这样就完成了。

public class csdn7 extends AppCompatActivity {

    private List<Image> list = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_csdn7);
        init();//初始化数据
        adapter ad = new adapter(csdn7.this,R.layout.item,list);
        ListView listview = findViewById(R.id.list_view);
        listview.setAdapter(ad);
    }
    
    private void init(){
        for(int i = 0; i < 5; i++){
            Image a = new Image("A",R.drawable.image1);
            list.add(a);
            Image b = new Image("B",R.drawable.image1);
            list.add(b);
            Image c = new Image("C",R.drawable.image1);
            list.add(c);
            Image d = new Image("D",R.drawable.image1);
            list.add(d);
            Image e = new Image("E",R.drawable.image1);
            list.add(e);
        }
    }
}

        现在只用修改item.xml文件中的内容,就可以做出各种复杂的界面了。

三、提升ListView的效率(优化)

        目前,上面的代码还有待优化的地方,如:adapter的getView()方法中,每次都将布局重新加载一遍,当ListView快速滚动的时候,运行效率会降低。再比如:每次在getView()方法中都会调用findViewById()方法获取控件实例。下面就对这两个问题进行优化。

修改adapter中的getView()方法中的代码,如下:

        getView()方法有一个convertView参数,这个参数用于将之前加载好的布局进行缓存,如果为null则加载布局,如果不为null则直接重用convertView。这样优化了第一个问题。

    public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        Image image = getItem(position);
        View view;
        if(convertView == null){
            view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
        }else{
            view = convertView;
        }
        ImageView image2 = view.findViewById(R.id.image);
        TextView name = view.findViewById(R.id.name);
        image2.setImageResource(image.getImageId());
        name.setText(image.getName());
        return view;
    }

再次修改getView()方法中的代码,如下:

        新增一个内部类ViewHolder,用于对控件的实例进行缓存,当convertView为null时,创建一个ViewHolder对象,将控件的实例都存放在ViewHolder里,调用setTag()方法,将ViewHolder对象存放在View中;不为null时,调用getTag,重新取出。这样优化了第二个问题。

   public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        Image image = getItem(position);
        View view;
        ViewHolder viewHolder;
        if(convertView == null){
            view = LayoutInflater.from(getContext()).inflate(resourceId,parent,false);
            viewHolder = new ViewHolder();
            viewHolder.image = view.findViewById(R.id.image);
            viewHolder.name = view.findViewById(R.id.name);
            view .setTag(viewHolder);

        }else{
            view = convertView;
            viewHolder = (ViewHolder) view.getTag();
        }
        viewHolder.image.setImageResource(image.getImageId());
        viewHolder.name.setText(image.getName());
        return view;
    }
    class ViewHolder{
        ImageView image;
        TextView name;
    }

四、ListView的点击事件

        点击事件是不可或缺的,前面的只是满足视觉上的效果,点击事件才是实际用途。

修改csdn7.java的代码,如下:

        原理同前面按钮的点击事件一致,创建实例后,调用setOnItemClickListener()方法为ListView注册监听器,通过参数i判断用户点击的子项。

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_csdn7);
        init();//初始化数据
        adapter ad = new adapter(csdn7.this,R.layout.item,list);
        ListView listview = findViewById(R.id.list_view);
        listview.setAdapter(ad);
        listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                Image image = list.get(i);
                Toast.makeText(csdn7.this, image.getName(), Toast.LENGTH_SHORT).show();
            }
        });
    }

效果如下:

 


希望本文章对你有帮助,如果你对Android开发感兴趣,请持续关注本专栏,帮助你从入门到项目实战,你将收获:Android基础开发、各种经典功能实现、项目实战、开发自己的APP、将APP上传应用商店、靠广告赚钱等等,持续更新ing......

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四月天行健

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值