发布时间:2025-12-09 20:01:23 浏览次数:3
目录
一、ListView的简单用法
二、进一步优化ListView界面
三、提升ListView的效率(优化)
四、ListView的点击事件
本篇文章主要讲解最常用的控件之一:ListView的使用。
当我们的程序有大量的数据需要展示的时候,可以借助ListView实现。ListView允许用户上下滑动滚动屏幕,如:查看QQ聊天记录。
首先新建一个新的活动,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"><ListViewandroid: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"};@Overrideprotected 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界面添加图片进行美观。效果如下:
新建一个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"><ImageViewandroid:id="@+id/image"android:layout_width="wrap_content"android:layout_height="wrap_content"/><TextViewandroid: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;}@Overridepublic 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<>();@Overrideprotected 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文件中的内容,就可以做出各种复杂的界面了。
目前,上面的代码还有待优化的地方,如: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;}点击事件是不可或缺的,前面的只是满足视觉上的效果,点击事件才是实际用途。
修改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() {@Overridepublic 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......