• Android学习之路(19) ListView详解


    一.ListView简介

    Android开发中,ListView是一个比较常用的控件。它以列表的形式 展示具体数据内容,并且能够根据数据的长度自适应屏幕显示。

    二.ListView简单用法

    代码部分

    1.布局界面 activity_main.xml 代码:

    
    
       
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.类文件 MainActivity.java 代码:

    package com.example.listview1;
    import androidx.appcompat.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.AdapterView;
    import android.widget.ArrayAdapter;
    import android.widget.ListView;
    import android.widget.TextView;
    import android.widget.Toast;
    public class MainActivity extends AppCompatActivity {
    //1、定义对象
         ListView listView;
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             setContentView(R.layout.activity_main);
             //2、绑定控件
             listView=(ListView) findViewById(R.id.list_view);
             //3、准备数据
             String[] data={"菠萝","芒果","石榴","葡萄", "苹果", "橙子", "西瓜","菠萝","芒果","石榴","葡萄", "苹果", "橙子", "西瓜","菠萝","芒果","石榴","葡萄", "苹果", "橙子", "西瓜"};
             //4、创建适配器 连接数据源和控件的桥梁
             //参数 1:当前的上下文环境
             //参数 2:当前列表项所加载的布局文件
             //(android.R.layout.simple_list_item_1)这里的布局文件是Android内置的,里面只有一个textview控件用来显示简单的文本内容
             //参数 3:数据源
             ArrayAdapter adapter=new ArrayAdapter<>(MainActivity.this,android.R.layout.simple_list_item_1,data);
             //5、将适配器加载到控件中
             listView.setAdapter(adapter);
             //6、为列表中选中的项添加单击响应事件
             listView.setOnItemClickListener(new AdapterView.OnItemClickListener() 
    {
             @Override
             public void onItemClick(AdapterView parent, View view, int i, long l) {
             String result=((TextView)view).getText().toString();
             Toast.makeText(MainActivity.this,"您选择的水果是:"+result,Toast.LENGTH_LONG).show();
             }
         });
       }
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    代码解析
    1.ArrayAdapter适配器

    • 1、ArrayAdapter适用亍数组或数据ArrayList(动态数组)。
    • 2、ArrayAdapter可以通过泛型来指定要适配的数据类型,然后在构造凼数中把要适配的数据传入。
    • 3、ArrayAdapter有多个构造函数的重载,可以根据实际情况选择最合适的一种。

    2.点击事件响应

    Parent: 指定哪个AdapterView(可能会有多个ListView,区分多个ListView)
    View: 为你点击的Listview的某一项的内容,来源于adapter。如用((TextView)view).getText().toString(),可以取出点击的这一项的内容,转为string 类型。
    Position: 指的是adapter的某一项的位置,如点击了listview第2项,而第2项对应 的是adapter的第2个数值,那此时position的值就为1了。注:这些数值都是从0开 始的。
    Id:id的值为点击了Listview的哪一项对应的数值,点击了listview第2项,那id就等于1。一般和position相同。

    三.定制 ListView 界面

    只能显示一段文本的listview太单调了,我们现在就来对listview的界面进行定制,让其丰富内容。

    代码部分

    1.布局界面 activity_main.xml 代码:

    
    
         
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    2.类文件 MainActivity.java 代码:

    package com.example.listview2;
    import androidx.appcompat.app.AppCompatActivity;
    import android.os.Bundle;
    import android.widget.ListView;
    import java.util.ArrayList;
    import java.util.List;
    public class MainActivity extends AppCompatActivity {
         //第一步:定义对象
         ListView listView;
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             setContentView(R.layout.activity_main);
             //第二步:绑定控件
             listView = (ListView) findViewById(R.id.list_view);
             //第三步:准备数据
             List fruitlist = new ArrayList<>();
             for (int i = 0; i <2 ; i++) {
                 Fruit pineapple=new Fruit(R.drawable.pineapple,"菠萝","¥16.9 元/KG");
                 fruitlist.add(pineapple);
                 Fruit mango = new Fruit(R.drawable.mango, "芒果","¥29.9 元/kg");
                 fruitlist.add(mango);
                 Fruit pomegranate = new Fruit(R.drawable.pomegranate, "石榴","¥15元/kg");
                 fruitlist.add(pomegranate);
                 Fruit grape = new Fruit(R.drawable.grape, "葡萄","¥19.9 元/kg");
                 fruitlist.add(grape);
                 Fruit apple = new Fruit(R.drawable.apple, "苹果","¥20 元/kg");
                 fruitlist.add(apple);
                 Fruit orange = new Fruit(R.drawable.orange, "橙子","¥18.8 元/kg");
                 fruitlist.add(orange);
                 Fruit watermelon = new Fruit(R.drawable.watermelon, "西瓜","¥28.8元/kg");
                 fruitlist.add(watermelon);
             }
             //第四步:设计每一个列表项的子布局
             //第五步:定义适配器 控件 -桥梁-数据
             FruitAdapter adapter=new FruitAdapter(MainActivity.this,R.layout.fruit_item,fruitlist);
             listView.setAdapter(adapter);
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    3.类文件 Fruit.java 代码:

    package com.example.listview2;
    public class Fruit {
    private int imageID;
    private String name;
    private String price;
         public int getImageID() {
             return imageID;
         }
         public String getName() {
             return name;
         }
         public String getPrice() {
             return price;
         }
         public Fruit(int imageID, String name, String price) {
             this.imageID = imageID;
             this.name = name;
             this.price = price;
         }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    4.类文件 FruitAdapter.java 代码:

    package com.example.listview2;
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    import java.util.List;
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    //用于将上下文、listview 子项布局的 id 和数据都传递过来
    public class FruitAdapter extends ArrayAdapter {
     public FruitAdapter(@NonNull Context context, int resource, @NonNull List objects) {
         super(context, resource, objects);
     }
    //每个子项被滚动到屏幕内的时候会被调用
         @NonNull
         @Override
         public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
         Fruit fruit=getItem(position);//得到当前项的 Fruit 实例
         //为每一个子项加载设定的布局
         View view=LayoutInflater.from(getContext()).inflate(R.layout.fruit_item,parent,false);
         //分别获取 image view 和 textview 的实例
         ImageView fruitimage =view.findViewById(R.id.fruit_image);
         TextView fruitname =view.findViewById(R.id.fruit_name);
         TextView fruitprice=view.findViewById(R.id.fruit_price);
         // 设置要显示的图片和文字
         fruitimage.setImageResource(fruit.getImageID());
         fruitname.setText(fruit.getName());
         fruitprice.setText(fruit.getPrice());
         return view;
         }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    5.布局界面 fruit_item.xml 代码:

    
    
         
         
         
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    代码解析

    1.引入动态数组ArrayList

    数组的缺点
    (1)数组长度固定
    (2)定义数组只能指定一种数据类型

    ArrayList:可以动态增加和缩减的索引序列,它是基于数组实现的list类

    List fruitlist = new ArrayList<>();

    List泛型里面既包括图片又包含文本,因此我们要定义一个Fruit类

    2.Fruit类

    public class Fruit {
    private int imageID;
    private String name;
    private String price;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在里面添加图片的id,名称和价格

    然后按下Alt+Insert键添加构造方法(Constructor)和Get方法(Getter)

    3.自定义适配器 控件 -桥梁-数据

    为什么要自定义适配器?
    原因在于,当我们想用一些其他的展现方式,或者是本案例我们需要的图文混排的呈现方式,这就需要DIY了。
    1.我们定义一个自定义适配器 FruitAdapter继承ArrayAdapter。
    2.自定义适配器中常用的方法:getCount、getView、getItem、getItemId。

    (1)创建好后需要添加泛型(也就是我们创建的Fruit类)

    (2)按下键盘上的Alt+Enter键创建构造方法(倒数第二个list)

    (3)重写getView方法

    4.inflate()方法

    inflate()方法的三个参数

    inflate(R.layout.fruit_item,parent,false)

    1、第一个参数是布局;(自己写的)
    2、第二个参数是父容器控件;
    3、第三个布尔值参数表明是否连接该布局和其父容器控件,在这里的情况设置 为false,因为系统已经插入了这个布局到父控件,设置为true将会产生多余的一 个View Group。

    四.提升ListView的运行效率

    目前我们ListView的运行效率是很低的,因为在FruitAdapter的 getView()方法中,每次都将布局重 新加载了一遍,将快速滚动的时候, 这将会成为性能的瓶颈。

    getView()方法中的convertView参数,用于将之前加载好的布局进行缓存,以便之 后可以进行重用。

    优化方法一:

    优化方法二:

    代码:

    package com.example.listview3;
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.ImageView;
    import android.widget.TextView;
    import java.util.List;
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    //用于将上下文、listview 子项布局的 id 和数据都传递过来
    public class FruitAdapter extends ArrayAdapter {
         public FruitAdapter(@NonNull Context context, int resource, @NonNull List objects) {
             super(context, resource, objects);
         }
         @NonNull
         @Override
         public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
             Fruit fruit=getItem(position);//获取当前项的 Fruit 实例
             View view;
             //新增一个内部类 ViewHolder,用于对控件的实例进行缓存
             ViewHolder viewHolder;
             if (convertView==null){
                 //为每一个子项加载设定的布局
                 view= LayoutInflater.from(getContext()).inflate(R.layout.fruit_item,parent,false);                     
                 viewHolder=new ViewHolder();
                 //分别获取 imageview 和 textview 的实例
                 viewHolder.fruitimage =view.findViewById(R.id.fruit_image);
                 viewHolder.fruitname =view.findViewById(R.id.fruit_name);
                 viewHolder.fruitprice=view.findViewById(R.id.fruit_price);
                 view.setTag(viewHolder);//将 viewHolder 存储在 view 中
             }else {
                 view=convertView;
                 viewHolder= (ViewHolder) view.getTag();//重新获取 viewHolder
         }
             // 设置要显示的图片和文字
             viewHolder.fruitimage.setImageResource(fruit.getImageID());
             viewHolder.fruitname.setText(fruit.getName());
             viewHolder.fruitprice.setText(fruit.getPrice());
             return view;
         }
         private class ViewHolder {
             ImageView fruitimage;
             TextView fruitname;
             TextView fruitprice;
         }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    五.ListView的点击事件

    ListView的滚动毕竟只是满足 了我们视觉上的效果,下面我们来学习ListView如何才能响 应用户的点击事件。

    代码:

    //第六步:listview 的点击事件
    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_LONG).show();
        }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    六.总结

  • 相关阅读:
    【抽代复习笔记】21-群(十五):循环群引理及定义
    Java基于SpringBoot的藏区特产销售系统的研究与实现
    死磕solidity之如何有效的节省gas.md
    C# 术语
    如何解决代理ip服务器连接问题
    Vue面试题以及解答(持续扩展中.....)
    [Numpy] 数组属性
    矩阵分析与应用(19)
    几个推荐程序员养成的好习惯
    SQL必需掌握的100个重要知识点:检索数据
  • 原文地址:https://blog.csdn.net/qq_32907491/article/details/133522952