Android RecyclerView
1、用法案例:在RecyclerView中展示水果图片以及水果名称
水果实体类:Fruit.kt
class Fruit(val fruitName: String, val fruitImage: Int)
RecyclerView中水果数据项布局: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>
适配器Adapter实现:FruitAdapter.kt
class FruitAdapter(private val fruits: List<Fruit>): RecyclerView.Adapter<FruitAdapter.ViewHolder>() { inner class ViewHolder(view: View): RecyclerView.ViewHolder(view) { var fruitImage: ImageView = view.findViewById(R.id.fruitImage) var fruitName: TextView = view.findViewById(R.id.fruitName) } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { Log.d("FruitAdapter", "onCreateViewHolder ...") val view = LayoutInflater.from(parent.context).inflate(R.layout.fruit_item, parent, false) return ViewHolder(view) } override fun onBindViewHolder(holder: ViewHolder, position: Int) { Log.d("FruitAdapter", "onBindViewHolder ...$position") holder.fruitImage.setImageResource(fruits[position].fruitImage) holder.fruitName.text = fruits[position].fruitName } override fun getItemCount(): Int { return fruits.size } }
这里我们首先定义了一个内部类ViewHolder,它要继承自RecyclerVIew.ViewHolder。然后ViewHolder的主构造函数中要传一个view参数,这个参数就是RecyclerView子项的最外层布局,这样我们就可以通过findViewById来获取布局的元素了
由于FruitAdapter继承RecyclerView.Adapter,那么就必须重写onCreateViewHolder()、onBindViewHolder()以及getItemCount()这三个方法。
onCreateViewHolder方法用来创建ViewHolder实例的,我们在这个方法中将fruit_item.xml布局加载进来,创建ViewHolder实例并返回该实例。
onBindViewHolder方法用于对RecyclerView子项数据进行赋值,会在每个子项被滚进到屏幕内的时候执行,这里通过position参数将对应的水果信息初始化到屏幕内的子项上。
getItemCount方法用于告诉RecyclerView一共有多少个子项,直接返回数据源的长度即可。
这里要说明一点:onCreateViewHolder中创建的组件会被RecyclerView内部机制缓存,当屏幕滚动产生新的子项时,onCreateViewHolder方法不会被执行,RecyclerView内部会使用缓存组件,大大提高了滚动效率。
展示页面逻辑:MainActivity.kt
class MainActivity : AppCompatActivity() { private var fruitList = ArrayList<Fruit>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val bind = ActivityMainBinding.inflate(layoutInflater) setContentView(bind.root) initFruits() Log.d("MainActivity", "fruitList: ${fruitList.size}") val manager = LinearLayoutManager(this) bind.recycleView.layoutManager = manager val fruitAdapter = FruitAdapter(fruitList) bind.recycleView.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)) } } }
自定义一个水果数组用来提供FruitAdater数据。
LinearLayoutManager用于指定RecyclerView的布局方式,这里是线性布局。一定要设置布局方式,不然RecyclerView不起作用,无法显示。
接着初始化FruitAdapter并适配到RecyclerView。
实现横向布局
修改fruit_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" //① 改为垂直布局 android:layout_width="80dp" //②设置宽度 android:layout_height="wrap_content"> <ImageView android:id="@+id/fruitImage" android:layout_gravity="center_horizontal" //③水平居中 android:layout_marginTop="10dp" //④设置顶部间距 android:layout_width="40dp" android:layout_height="40dp"/> <TextView android:id="@+id/fruitName" android:layout_gravity="center_horizontal" //⑤水平居中 android:layout_marginTop="10dp" //⑥设置顶部间距 android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
修改MainActivity.kt
manager.orientation = LinearLayoutManager.HORIZONTAL
只需要将布局的排列方式改为横向排列即可,默认为纵向排列。
实现瀑布流布局:StaggeredGridLayoutManager
修改fruit_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_margin="5dp" //①让子项之间有间距,不至于紧贴在一起,比较美观 android:layout_width="match_parent" //②改为match_parent,因为瀑布流的宽度应该是根据布局的列数来自动适配的,而不是一个固定值 android:layout_height="wrap_content"> <ImageView android:id="@+id/fruitImage" android:layout_gravity="center_horizontal" android:layout_marginTop="10dp" android:layout_width="40dp" android:layout_height="40dp"/> <TextView android:id="@+id/fruitName" android:layout_gravity="left" //③为了美观展示 android:layout_marginTop="10dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>
修改MainActivity.kt
使用瀑布流布局,StaggeredGridLayoutManager的构造函数接收两个参数,第一个参数用于指定布局展示的列数,第二个参数用于指定布局的排列方向。
val manager = StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL)
创建了一个函数getRandomLengthString,就是为了随机增加水果名称的字数,尽可能展示瀑布流的布局效果。
private fun initFruits() { repeat(2) { fruitList.add(Fruit(getRandomLengthString("apple"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("pear"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("banana"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("orange"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("peach"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("nectarine"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("apricot"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("plum"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("prune"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("persimmon"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("lemon"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("grape"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("watermelon"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("pineapple"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("blueberry"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("strawberry"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("waxberry"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("mulberry"), R.drawable.fruit)) fruitList.add(Fruit(getRandomLengthString("cherrytomato"), R.drawable.fruit)) } } private fun getRandomLengthString (str: String): String { val n = (1..20).random() var name = StringBuilder() repeat(n) { name.append(str) } return name.toString() }
网格布局:GridLayoutManager
修改MainActivity.kt
val manager = GridLayoutManager
posted on 2023-06-29 16:32 Devil'soul 阅读(34) 评论(0) 编辑 收藏 举报