Android 定制ListView的界面

1、创建MainActivity以及对应的布局文件

<?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="wrap_content"/>

</LinearLayout>

布局文件里简单使用了ListView标签

2、创建ListView的item布局: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_gravity="center_vertical"
        android:layout_marginLeft="10dp"
        android:layout_width="40dp"
        android:layout_height="40dp"/>

    <TextView
        android:id="@+id/fruitName"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

布局里包含两个元素ImageView和TextView,用来展示水果图片和名称

3、定义水果类,方便管理:Fruit.kt

class Fruit(val name: String, val imageId: Int)

4、定义水果的适配器:FruitAdapter.kt

class FruitAdapter(activity: Activity, private 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 imageView = view.findViewById<ImageView>(R.id.fruitImage)
        val fruitName: TextView = view.findViewById(R.id.fruitName)
        val fruit = getItem(position)
        if (fruit != null) {
            imageView.setImageResource(fruit.imageId)
            fruitName.text = fruit.name
        }
        return view
    }
}

这里继承了ArrayAdapter,然后重写getView方法,把水果属性初始化到ListView每个数据项上

getView()方法会在每个子项被滚动到屏幕内的时候会被调用

5、在MainActivity中展示ListView等逻辑:MainActivity.kt

class MainActivity : AppCompatActivity() {

    val fruitList = ArrayList<Fruit>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val bind = ActivityMainBinding.inflate(layoutInflater)
        setContentView(bind.root)
        initFruits()
        val fruitAdapter = FruitAdapter(this, R.layout.fruit_item, fruitList)
        bind.listView.adapter = fruitAdapter
    }

    private fun initFruits() {
        repeat(2) {
            fruitList.add(Fruit("apple", R.drawable.fruit))
            fruitList.add(Fruit("pear", R.drawable.fruit))
            fruitList.add(Fruit("banana", R.drawable.fruit))
            fruitList.add(Fruit("orange", R.drawable.fruit))
            fruitList.add(Fruit("peach", R.drawable.fruit))
            fruitList.add(Fruit("nectarine", R.drawable.fruit))
            fruitList.add(Fruit("apricot", R.drawable.fruit))
            fruitList.add(Fruit("plum", R.drawable.fruit))
            fruitList.add(Fruit("prune", R.drawable.fruit))
            fruitList.add(Fruit("persimmon", R.drawable.fruit))
            fruitList.add(Fruit("lemon", R.drawable.fruit))
            fruitList.add(Fruit("grape", R.drawable.fruit))
            fruitList.add(Fruit("watermelon", R.drawable.fruit))
            fruitList.add(Fruit("pineapple", R.drawable.fruit))
            fruitList.add(Fruit("blueberry", R.drawable.fruit))
            fruitList.add(Fruit("strawberry", R.drawable.fruit))
            fruitList.add(Fruit("waxberry", R.drawable.fruit))
            fruitList.add(Fruit("mulberry", R.drawable.fruit))
            fruitList.add(Fruit("cherrytomato", R.drawable.fruit))
        }
    }
}

逻辑很简单,初始化水果数据,其中repeat函数将水果添加了两遍。然后创建FruitAdapter,接着把Adapter赋值给ListView。

核心逻辑还是在数据项布局:fruit_item.xml以及FruitAdapter的getView方法,用户可以根据自己的实际需求去进行设计,这样就可以实现LiveView界面的定制化开发。

这里有一个很有意思的现象:如果ListView的layout_height的属性不是match_parent,即高度不是固定的话,那么在FruitAdapter的getView方法会重复执行几遍;

举个例子,假设ListView能同时显示的item子项为10项,那么ListView初始化的时候,getView应该执行十次,来初始化能看见的子项数据,但是如果ListView的layout_height的属性不是match_parent,ListView可能内部要经过一些复杂的逻辑来计算当前ListView的高度应该显示几行数据,那么就会导致最终getView的执行次数为30次,这十个子项被重复渲染了三次。如果追求效率的提升,在业务场景满足的情况下,尽可能设置ListView的layout_height的属性为match_parent

posted on 2023-06-28 15:13  Devil'soul  阅读(48)  评论(0编辑  收藏  举报

导航