😄作者简介: 小曾同学.com,一个致力于测试开发的博主⛽️,主要职责:测试开发、CI/CD
如果文章知识点有错误的地方,还请大家指正,让我们一起学习,一起进步。
😊 座右铭:不想当开发的测试,不是一个好测试✌️。
如果感觉博主的文章还不错的话,还请点赞、评论、收藏哦!👍
在上一篇文章中,我们介绍了 ListView的简单使用,只是简单的展示一段文本,现在我们开始对 ListView 界面进行定制。和网上其他案例类似,也是以水果图片为例,但本篇文章更加详细。
主要代码文件:
-
MainActivity 我们定义为
DIYListViewActivity
,对应的 layout 布局文件为activity_diylist_view.xml;
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent"> </ListView> </LinearLayout>
-
Fruit 实体类:用于描述水果的属性信息,对应的 layput 布局文件为 fruit_item.xml
-
FruitAdapter:自定义适配器
因为适配器是连接数据和视图的桥梁,视图是 ListView、而水果数据是数据,我们先定义一个实体类 Fruit ,作为 ListView 适配器的适配类型。
Fruit 类中有两个字段:
-
name:水果名字
-
imageId :水果图片id
class Fruit(val name:String,val imageId:Int)
在 ListView 文章中,ListView 的子项是一段文本,我们采用的是 Android 内置的布局文件,而我们定制化 ListView 界面的话,在本篇文章中 ListView 的子项水果数据,所以我们要新增一个布局文件,用于水果数据的具体展示(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:layout_height="60dp">
<ImageView
android:id="@+id/fruitImage"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp"/>
<TextView
android:id="@+id/fruitName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginLeft="10dp" />
</LinearLayout>
我们还需要自定义一个适配器 FruitAdapter ,用于在 ListView 中显示水鬼,这个适配器继承 ArrayAdapter,并将范型指定为 Fruit 类,(范型:允许我们编写可以处理多种类型的代码,而不需要为每种类型编写重复的代码)
自定义适配器方法:继承现有适配器的实现类,例如 ArrayAdapter,重写 getView() 方法,在 getView() 方法中,创建一个 itemView
,它是每个列表项的根视图。然后,我们通过调用 findViewById
来获取到自定义布局中的 ImageView
、TextView
控件,然后,从数据源中获取对应位置的水果对象,并将水果对象的图片和名称设置给对应的视图控件,最后,返回 itemView
。
class FruitAdapter (activity: Activity,val resourceId: Int,data:List<Fruit>):ArrayAdapter<Fruit>(activity,resourceId,data) {
override fun getView(position: Int,convertView: View?,parent:ViewGroup):View{
val view = LayoutInflater.from(context).inflate(resourceId,parent,false)
val fruitImage:ImageView = view.findViewById(R.id.fruitImage)
val fruitName:TextView = view.findViewById(R.id.fruitName)
val fruit = getItem(position) //获取当前项的Fruit实例
if(fruit != null){
fruitImage.setImageResource(fruit.imageId)
fruitName.text = fruit.name
}
return view
}
}
详解:
-
FruitAdapter 定义了一个主构造函数,用于将 Activity 的实例,ListView子项布局和 id 和数据源传递进来。
class FruitAdapter (activity: Activity,val resourceId: Int,data:List<Fruit>):ArrayAdapter<Fruit>(activity,resourceId,data)
-
activity: Activity
是构造函数的参数,表示当前的Activity -
val resourceId: Int
是构造函数的参数,表示列表项的布局资源 id -
data:List<Fruit>
是构造函数的参数,闭表示要显示的水果数据列表这里说的构造函数是 FruitAdapter 类的构造函数,在构造函数中,
activity: Activity
参数用于接收传入的 Activity 对象,并将其传递给父类 ArrayAdapter 的构造函数。通过这种方式,FruitAdapter 类可以使用传入的 Activity 对象来执行一些与 UI 相关的操作,例如使用LayoutInflater
创建视图、获取资源等。
-
重写
getView()
方法,用于获取指定位置上的列表项的视图。override fun getView(position: Int,convertView: View?,parent:ViewGroup):View{ val view = LayoutInflater.from(context).inflate(resourceId,parent,false) val fruitImage:ImageView = view.findViewById(R.id.fruitImage) val fruitName:TextView = view.findViewById(R.id.fruitName) val fruit = getItem(position) //获取当前项的Fruit实例 if(fruit != null){ fruitImage.setImageResource(fruit.imageId) fruitName.text = fruit.name }
LayoutInflater.from(context)
创建 LayoutInflater 对象,用于将布局资源转换为视图;inflate(resourceId,parent,false)
从指定的布局资源 ID 创建视图,parent 是父视图,false 表示不将视图附加到父视图上,即只让在父布局中声明的 layput 属性生效。view.findViewById()
获取视图中的 fruitImage、fruitNamegetItem(position)
方法从数据源中获取指定位置的水果对象,即获取当前项的 Fruit 实例。
if(fruit != null) 如果水果对象不为空,调用setImageResource()
和setText()
方法设置显示的图片和文字
- 最后,返回 设置好数据的视图
return view
。
好了,自定义适配器我们已经准备好了,接下来,我们写MainActivity中的逻辑代码
class DIYListViewActivity : AppCompatActivity() {
private val fruitList = ArrayList<Fruit>()
@SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_diylist_view)
initFruits() //初始化水果数据
var listView: ListView = findViewById(R.id.listView)
val adapter = FruitAdapter(this,R.layout.fruit_item,fruitList)
listView.adapter = adapter
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.listView)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
}
// 初始化水果数据,
private fun initFruits() {
repeat(10){
fruitList.add(Fruit("apple", R.drawable.apple_pic))
fruitList.add(Fruit("banana", R.drawable.banana_pic))
}
}
}
// repeat函数是kotlin中常用标准函数,
Demo 展示
至此,定制化 ListView 界面 我们已经完成啦,赶快动手实践下吧。