一.ListView简介
在Android开发中,ListView是一个比较常用的控件。它以列表的形式 展示具体数据内容,并且能够根据数据的长度自适应屏幕显示。
二.ListView简单用法
代码部分
1.布局界面 activity_main.xml 代码:
<?xml version="1.0" encoding="utf-8"?><LinearLayout 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=".MainActivity"> <ListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent"/></LinearLayout>
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<String> 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.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 代码:
<?xml version="1.0" encoding="utf-8"?><LinearLayout 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=".MainActivity"> <ListView android:id="@+id/list_view" android:layout_width="match_parent" android:layout_height="match_parent"/></LinearLayout>
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<Fruit> 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); }}
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; }}
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<Fruit> { public FruitAdapter(@NonNull Context context, int resource, @NonNull List<Fruit> 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; }}
5.布局界面 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:orientation="horizontal" android:layout_height="wrap_content"> <ImageView android:id="@+id/fruit_image" android:src="@drawable/apple" android:layout_width="100dp" android:layout_height="80dp"/> <TextView android:id="@+id/fruit_name" android:layout_gravity="center_vertical" android:textSize="30sp" android:textColor="#000000" android:text="name" android:layout_marginLeft="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/fruit_price" android:layout_gravity="center_vertical" android:textColor="#ff0000" android:text="price" android:textSize="30sp" android:layout_marginLeft="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/></LinearLayout>
代码解析
1.引入动态数组ArrayList
数组的缺点
(1)数组长度固定
(2)定义数组只能指定一种数据类型
** ArrayList:可以动态增加和缩减的索引序列,它是基于数组实现的list类**
List<Fruit> fruitlist = new ArrayList<>();
List泛型里面既包括图片又包含文本,因此我们要定义一个Fruit类
2.Fruit类
public class Fruit {private int imageID;private String name;private String price;}
** 在里面添加图片的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<Fruit> { public FruitAdapter(@NonNull Context context, int resource, @NonNull List<Fruit> 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; }}
五.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(); } });
六.总结
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/indeedes/article/details/119530068