一、概览
recyclerView.scrollToPosition | 滚动到某个item索引位置 |
adapter.notifyItemInserted( ) | 局部刷新?通知列表有数据插入。 |
notifyDataSetChanged( ) | 全部刷新,不管是新增、删除、修改。 |
二、基本使用
2.1 添加依赖
implementation("androidx.recyclerview:recyclerview:1.2.1")
2.2 布局中引入
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
2.3 编写适配器Adapter
class FruitAdapter(val fruitList: List<Fruit>) : RecyclerView.Adapter<FruitAdapter.ViewHolder>() {
//加载布局并绑定到子选项
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.fruit_item, parent, false)
return ViewHolder(view)
}
//子选项的中的各个控件赋值数据
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val fruit = fruitList[position]
holder.fruitImage.setImageResource(fruit.imageId)
holder.fruitName.text = fruit.name
}
//设定子选项数量
override fun getItemCount() = fruitList.size
//获取子选项布局中的各个控件
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val fruitImage: ImageView = view.findViewById(R.id.fruitImage)
val fruitName: TextView = view.findViewById(R.id.fruitName)
}
}
2.4 在UI中使用
private val dataList = ArrayList<Fruit>()
//线性布局,设置横向显示
val layoutManager1 = LinearLayoutManager(this)
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
//瀑布流布局,参数一列数、参数二方向
val layoutManager2 = StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL)
recyclerView.layoutManager = layoutManager
recyclerView.adapter = FruitAdapter(dataList)
三、显示不同类型的 item
例如消息列表存在:左边收到的消息item、右边发出的消息item:
- 不同的 item 都需要单独编写对应的ViewHolder;
- 在 getItemViewType() 中,形参position 是 item的索引,结合数据源判断什么情况返回什么 item类型(用Int值表示);
- 在 onCreateViewHolder() 中,形参viewType 就是上一步返回的值, 进行判断创建对应 item布局并绑定到对应的ViewHolder;
- 在 onBindViewHolder() 中,对形参holder 进行判断是哪种类型,然后分别处理各自的赋值和点击事件。
class MsgAdapter(val msgList: List<Msg>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun getItemViewType(position: Int): Int {
val msg = msgList[position]
return msg.type
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = if (viewType == Msg.TYPE_RECEIVED) {
val view = LayoutInflater.from(parent.context).inflate(R.layout.msg_left_item, parent, false)
LeftViewHolder(view)
} else {
val view = LayoutInflater.from(parent.context).inflate(R.layout.msg_right_item, parent, false)
RightViewHolder(view)
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val msg = msgList[position]
when (holder) {
is LeftViewHolder -> holder.leftMsg.text = msg.content
is RightViewHolder -> holder.rightMsg.text = msg.content
else -> throw IllegalArgumentException()
}
}
override fun getItemCount() = msgList.size
inner class LeftViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val leftMsg: TextView = view.findViewById(R.id.leftMsg)
}
inner class RightViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val rightMsg: TextView = view.findViewById(R.id.rightMsg)
}
}
四、合并显示多个 Adapter
当界面有头部、内容、底部三个区域都用到了列表显示,可以合并他们避免写三个 RecyclerView 实例分别进行设置:
- 写三个xml布局:Header、Content、Footer;
- 写三个继承自RecyclerViewer.Adapter的适配器;
- 创建ConcatAdapter并添加需要合并的适配器。