
Andriod 自定义ListView的列表项
发布日期:2021-05-07 23:05:21
浏览次数:24
分类:原创文章
本文共 9870 字,大约阅读时间需要 32 分钟。
文章目录
1 自定义ListView列表项
- LIstView支持自定义列表项,此时需要自定义布局文件
- 在自定义布局文件需要使用类型数据的时候,此时需要自定义适配器
1.1 自定义布局文件
- 新建layout.xml文件
- 新建的layout布局是列表项的布局,相当于在列表项中进行自定义布局
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content"> <ImageView android:layout_width="100dp" android:layout_height="80dp" android:id="@+id/fruit_image" android:src="@drawable/apple" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/fruit_name" android:text="name" android:textSize="30sp" android:textColor="#000000" android:layout_gravity="center_vertical" android:layout_marginLeft="20dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/fruit_price" android:text="name" android:textSize="30sp" android:textColor="#ff0000" android:layout_gravity="center_vertical" android:layout_marginLeft="40dp" /></LinearLayout>
1.2 自定义Adapter加载自定义布局
- 自定义Adapter需要继承一个父类适配器,例如:ArrayAdapter, 并覆盖其中的构造方法与**getView()**方法
- 自定义构造方法:必须是有参构造方法
- 参数一:上下文环境,例如MainActivity.this
- 参数二:布局文件的ID,为R.layout.layout
- 参数三:为列表类型的数据源
// 参数1 为上下文, 参数2 为layout布局的id, 参数3 为数据源 public FruitAdapter(@NonNull Context context, int resource, @NonNull List<Fruit> objects) { super(context, resource, objects); }
- getView方法,填充自定义布局
使用步骤:
- 获取传入数组的数据项,数组或者列表在构造方法中传入
- 将自定义布局转化为View类型,使用 **inflate()**方法进行填充
LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout, parent, false);
- 在view中获取其中的控件,填充其中的信息
- 最后返回布局view
// 屏幕滑动的时候,调用子项@NonNull@Overridepublic View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { //1. 得到当前fruit实例, 可见 fruit在适配器中 Fruit fruit = getItem(position); // 2. 为子项加载布局, 传入到ViewGroup中 View view = LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout, parent, false); // 3. 获取View中的控件,并为控件赋值 ImageView fruitImage = view.findViewById(R.id.fruit_image); TextView fruitName = view.findViewById(R.id.fruit_name); TextView fruitPrice = view.findViewById(R.id.fruit_price); // 4. 设置图片以及文件资源 fruitImage.setImageResource(fruit.getImageID()); fruitName.setText(fruit.getName()); fruitPrice.setText("$" + fruit.getPrice() / 100 + "/KG"); // 5. 返回设置好的布局 return view;}
2 进行ListView进行适配
2.1 自定义JavaBean
package com.hlq.sz_ch_listviewdemo02;public class Fruit { private int imageID; private String name; private long price; public void setImageID(int imageID) { this.imageID = imageID; } public void setName(String name) { this.name = name; } public void setPrice(long price) { this.price = price; } public int getImageID() { return imageID; } public String getName() { return name; } public long getPrice() { return price; } public Fruit(int imageID, String name, long price) { this.imageID = imageID; this.name = name; this.price = price; } public Fruit() { }}
2.2 自定义布局与ListIView绑定
2.2.1 主布局文件
<?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.2.2 获取自定义布局文件,填充主布局文件
- 在内存中新建自定义列表适配器,
new FruitAdapterEnhance(MainActivity.this, R.layout.fruit_layout, fruits);
- 绑定适配器,
listView.setAdapter(fruitAdapter);
import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.AdapterView;import android.widget.ListView;import android.widget.TextView;import android.widget.Toast;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity { // 内部对象 private ListView listView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 1. 绑定控件 listView = (ListView)findViewById(R.id.list_view); // 2. 准备数据 List<Fruit> fruits = new ArrayList<>(); for (int i = 0; i < 2; ++i) { Fruit pineApple = new Fruit(R.drawable.pineapple, "菠萝", 1690); fruits.add(pineApple); Fruit mango = new Fruit(R.drawable.mango, "芒果", 2990); fruits.add(mango); Fruit grape = new Fruit(R.drawable.grape, "葡萄", 1990); fruits.add(grape); Fruit pomegranate = new Fruit(R.drawable.pomegranate, "石榴", 1500); fruits.add(pomegranate); Fruit apple = new Fruit(R.drawable.apple, "苹果", 2000); fruits.add(apple); Fruit watermelon = new Fruit(R.drawable.watermelon, "西瓜", 2880); fruits.add(watermelon); Fruit orange = new Fruit(R.drawable.orange, "橘子", 1880); fruits.add(orange); } // 3. 设置子布局 // 4. 定义适配器, 控件与数据的桥梁 FruitAdapterEnhance fruitAdapter = new FruitAdapterEnhance(MainActivity.this, R.layout.fruit_layout, fruits); listView.setAdapter(fruitAdapter); // 5. 设置点击事件 // 4 为列表适配器增加响应事件 listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){ @Override public void onItemClick(AdapterView<?> parent, View view, int position , long i) { // 从View中获取信息, 此时的View为点击的View TextView textView = view.findViewById(R.id.fruit_name); String result = textView.getText().toString(); Toast.makeText(MainActivity.this, "选择的选项为: " + result, Toast.LENGTH_SHORT).show(); // 上下文必须指定为MainActivity.this } }); }}
3 对自定义布局的加载进行优化
- 优化思想:在用户进行滑动的时候,每一个列表项都需要重新加载,由于布局要加载到内存,造成ListView的性能下降
- 为了优化性能,可以将ListView的布局保存,不必重新加载,每一个列表项只是将数据填入到布局中
3.1 对自定义列表适配器进行优化
- 自定义内部类,包含列表项中的布局控件,此时为ViewHolder
- 第一次加载时,View的引用为null, 将ViewHolder内部类存储在view中,使用
view.setTag(viewHolder);
- 当view的引用不为null的时候,获取view布局,并获取其中的内部类进行布局的填充
view = convertView; viewHolder = (ViewHolder)view.getTag();
- 每一个项目的加载都需要设置信息,因此在ViewHolder内部类中填充信息。获取View控件,进行资源的设置,例如:
viewHolder.getFruitImage().setImageResource(fruit.getImageID());viewHolder.getFruitName().setText(fruit.getName());
3.2 完整优化代码
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 androidx.annotation.NonNull;import androidx.annotation.Nullable;import java.util.List;public class FruitAdapterEnhance extends ArrayAdapter<Fruit> { // 构造函数 // 参数1 为上下文, 参数2 为layout布局的id, 参数3 为数据源 public FruitAdapterEnhance(@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) { //1. 得到当前fruit实例, 从适配的位置获取 使得控件与数据项一一对应 Fruit fruit = getItem(position); // 1. 新增ViewHolder ViewHolder viewHolder; View view; // 2. 是否加载了布局 if (convertView == null) { // 2.1 没有加载布局的时候,使用子布局 view = LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout, parent, false); viewHolder = new ViewHolder(); viewHolder.setFruitImage(view.findViewById(R.id.fruit_image)); viewHolder.setFruitName(view.findViewById(R.id.fruit_name)); viewHolder.setFruitPrice(view.findViewById(R.id.fruit_price)); // 2.2 将viewHolder存储与view中 view.setTag(viewHolder); } else { // 从新获取viewHolder view = convertView; viewHolder = (ViewHolder)view.getTag(); } // 3. 设置viewGroup中的内容 viewHolder.getFruitImage().setImageResource(fruit.getImageID()); viewHolder.getFruitName().setText(fruit.getName()); viewHolder.getFruitPrice().setText("$" + fruit.getPrice() / 100 + "/Kg");// // 2. 为子项加载布局, 传入到ViewGroup中// View view = LayoutInflater.from(getContext()).inflate(R.layout.fruit_layout, parent, false);//// // 3. 获取View中的控件,并为控件赋值// ImageView fruitImage = view.findViewById(R.id.fruit_image);// TextView fruitName = view.findViewById(R.id.fruit_name);// TextView fruitPrice = view.findViewById(R.id.fruit_price);//// // 4. 设置图片以及文件资源// fruitImage.setImageResource(fruit.getImageID());// fruitName.setText(fruit.getName());// fruitPrice.setText("$" + fruit.getPrice() / 100 + "/KG");//// // 5. 返回设置好的布局 return view; } // 3设置内部类,加载布局,只需提供数据,加快读取速度 private class ViewHolder{ ImageView fruitImage; TextView fruitName; TextView fruitPrice; public ImageView getFruitImage() { return fruitImage; } public TextView getFruitName() { return fruitName; } public TextView getFruitPrice() { return fruitPrice; } public void setFruitImage(ImageView fruitImage) { this.fruitImage = fruitImage; } public void setFruitName(TextView fruitName) { this.fruitName = fruitName; } public void setFruitPrice(TextView fruitPrice) { this.fruitPrice = fruitPrice; } }}
4 结果
发表评论
最新留言
不错!
[***.144.177.141]2025年03月30日 02时58分29秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Docker 服务
2019-03-06
第一眼就心动的人还怎么做朋友
2019-03-06
Cassandra数据建模
2019-03-06
Elasticsearch Web管理工具
2019-03-06
Git 配置SSH公钥、私钥
2019-03-06
极客时间离线课堂
2019-03-06
Spring Session
2019-03-06
koa2 中间件里面的next到底是什么
2019-03-06
在create-react-app创建的项目下允许函数绑定运算符
2019-03-06
博客园新闻频道开始公开测试
2019-03-06
评论表聚集索引引起的评论超时问题
2019-03-06
博客园上海俱乐部4月份活动通知邀请函已经发出!
2019-03-06
上周热点回顾(5.24-5.30)
2019-03-06
Internet Explorer 10 专题上线
2019-03-06
云计算之路-阿里云上:0:25~0:40网络存储故障造成网站不能正常访问
2019-03-06
网站故障公告1:使用阿里云RDS之后一个让人欲哭无泪的下午
2019-03-06
上周热点回顾(12.31-1.6)
2019-03-06
上周热点回顾(1.21-1.27)
2019-03-06
上周热点回顾(6.3-6.9)
2019-03-06
上周热点回顾(8.12-8.18)
2019-03-06