【ListView】

简单(String)

先为ListView 指定一个id,然后将宽度和高度都设置为match_parent,这样ListView 就占满了整个布局的空间。

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" />
</LinearLayout>
kt 复制代码
class MainActivity : AppCompatActivity() {
	private val data = listOf("Apple", "Banana", "Orange", "Watermelon", "Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango", "Apple", "Banana", "Orange", "Watermelon", "Pear", "Grape", "Pineapple", "Strawberry", "Cherry", "Mango")
	
	override fun onCreate(savedInstanceState: Bundle?) { 
		super.onCreate(savedInstanceState)
		setContentView(R.layout.activity_main)
		val adapter = 
			ArrayAdapter<String>(
				this, //Activity 的实例
				android.R.layout.simple_list_item_1, //ListView 子项布局的id
				data //数据源
			)
		//用ListView 的setAdapter()方法,将构建好的适配器对象传递进去
		listView.adapter = adapter
	} 
}

定制 item(Fruit)

kt 复制代码
class Fruit(val name:String, val imageId: Int)
xml 复制代码
<!-- fruit_item.xml -->
<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>
kt 复制代码
// FruitAdapter 定义了一个主构造函数:
class FruitAdapter(
	activity: Activity, //Activity 的实例
	val resourceId: Int, //ListView 子项布局的id
	data: List<Fruit> //数据源
) : ArrayAdapter<Fruit>(activity, resourceId, data) {
	//重写了getView()方法,这个方法在每个子项被滚动到屏幕内的时候会被调用。
	override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { 
		//首先,使用LayoutInflater来为这个子项加载我们传入的布局
		val view = LayoutInflater.from(context).inflate(resourceId, parent, false)
		//接下来,调用View的findViewById()方法,分别获取到ImageView 和TextView 的实例
		val fruitImage: ImageView = view.findViewById(R.id.fruitImage)
		val fruitName: TextView = view.findViewById(R.id.fruitName)
		
		//然后,通过getItem()方法得到当前项的Fruit实例
		val fruit = getItem(position)

		//分别调用它们的setImageResource()和setText()方法设置显示的图片和文字
		if (fruit != null) {
			fruitImage.setImageResource(fruit.imageId)
			fruitName.text = fruit.name 
		}
		
		return view 
	}
}
kt 复制代码
class MainActivity : AppCompatActivity() {
	private val fruitList = ArrayList<Fruit>()
	override fun onCreate(savedInstanceState: Bundle?) { 
		super.onCreate(savedInstanceState) 
		setContentView(R.layout.activity_main) 
	
		initFruits() // 初始化水果数据
		val adapter = FruitAdapter(this, R.layout.fruit_item, fruitList)
		listView.adapter = adapter 
	}
	private fun initFruits() { 
		repeat(2) {
			fruitList.add(Fruit("Apple", R.drawable.apple_pic)) 
			fruitList.add(Fruit("Banana", R.drawable.banana_pic)) 
			fruitList.add(Fruit("Orange", R.drawable.orange_pic)) 
			fruitList.add(Fruit("Watermelon", R.drawable.watermelon_pic)) 
			fruitList.add(Fruit("Pear", R.drawable.pear_pic)) 
			fruitList.add(Fruit("Grape", R.drawable.grape_pic)) 
			fruitList.add(Fruit("Pineapple", R.drawable.pineapple_pic)) 
			fruitList.add(Fruit("Strawberry", R.drawable.strawberry_pic)) 
			fruitList.add(Fruit("Cherry", R.drawable.cherry_pic)) 
			fruitList.add(Fruit("Mango", R.drawable.mango_pic))
		} 
	} 
}

repeat函数是Kotlin 中另外一个非常常用的标准函数,它允许你传入一个数值n,然后会把Lambda 表达式中的内容执行n

提高效率

convertView参数用于将之前加 载好的布局进行缓存,以便之后进行重用:

kt 复制代码
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: View
		if (convertView == null) {
			view = LayoutInflater.from(context).inflate(resourceId, parent, false)
		} else {
			view = convertView
		}
		...
	}
}

继续优化:

kt 复制代码
class FruitAdapter(activity: Activity, val resourceId: Int, data: List<Fruit>) : ArrayAdapter<Fruit>(activity, resourceId, data) {
	//新增了一个内部类ViewHolder,用于对ImageView和TextView的控件实例进行缓存
	inner class ViewHolder(val fruitImage: ImageView, val fruitName: TextView)
	
	override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { 
		val view: View
		val viewHolder: ViewHolder 
		if (convertView == null) {
			view = LayoutInflater.from(context).inflate(resourceId, parent, false) 
			val fruitImage: ImageView = view.findViewById(R.id.fruitImage)
			val fruitName: TextView = view.findViewById(R.id.fruitName) 
			viewHolder = ViewHolder(fruitImage, fruitName)
			//View的setTag()方法,将ViewHolder对象存储在View中
			view.tag = viewHolder
		} else {
			view = convertView
			viewHolder = view.tag as ViewHolder 
		}
		
		val fruit = getItem(position)
		if (fruit != null) {
			viewHolder.fruitImage.setImageResource(fruit.imageId)
			viewHolder.fruitName.text = fruit.name 
		}
		return view 
	}
}
相关推荐
AFinalStone36 分钟前
Android12 U盘插拔链路源码全解析(五):Framework层(下) StorageManagerService
android·frameworks
林九生2 小时前
【实用技巧】MySQL 绿色版一键路径更新脚本详解 —— update_path.bat 深度解析
android·数据库·mysql
故渊at3 小时前
第十三板块:Android 综合架构与未来演进 | 第三十一篇:Android 架构演进与 Fuchsia OS 的挑战
android·架构·宏内核·微内核·fuchsia·ipc 性能博弈
aqi003 小时前
一文速览 HarmonyOS 6.1.1 推出的十个新特性
android·华为·harmonyos·鸿蒙·harmony
matrixmind13 小时前
aiomysql:异步场景下的 MySQL 驱动
android·数据库·mysql·其他
随遇丿而安3 小时前
第8周:弹窗 / 提示组件全功能与弹窗优化
android
zh_xuan3 小时前
诡异Bug:输入框删除字符,却越删越多
android·bug
nwsuaf_huasir4 小时前
matlab绘制尺寸和字体合适的图片插入到latex的方法
android·开发语言·matlab
future_li4 小时前
Speed Tools:一套低侵入的 Android 插件化 + 动态换肤 + 字体切换框架
android
杊页4 小时前
第一板块:Android 系统基石与运行原理 | 第二篇:Android 编译、打包与安装机制
android·操作系统