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) 编辑 收藏 举报