RecyclerView控件

首先,他并不是系统自带的控件,而是在androidx中的,也就是还需要从外部导入。不过好在IDEA已经帮我们导入过了,在build.gralde

1
2
3
4
5
6
7
8
9
10
dependencies {

implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

导入之后就可以正常使用了

普通使用

  1. 首先直接在layout布局中声明一个recyclerView控件
    1
    2
    3
    4
    <androidx.recyclerview.widget.RecyclerView
    android:id="@+id/recyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
  2. 然后继承他的适配器,直接放实例代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class Girl(val girlName: String, val girlImg: Int){}
    class GirlAdapter(val girlList: List<Girl>) :
    RecyclerView.Adapter<GirlAdapter.ViewHolder>() {
    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    val girlName = view.findViewById<TextView>(R.id.girlName)
    val girlImg = view.findViewById<ImageView>(R.id.girlImg)
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val view = LayoutInflater.from(parent.context)
    .inflate(R.layout.girl_item, parent, false)
    return ViewHolder(view)
    }

    override fun getItemCount() = girlList.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val girl = girlList[position]
    holder.girlImg.setImageResource(girl.girlImg)
    holder.girlName.text = girl.girlName
    }
    }
    相较于listview:
    1. 他只需要接受一个data的参数,更容易理解其中的内容
    2. 他需要实现三个方法和一个内部类
属性 释义
ViewHolder 用来简化操作,提前维护好view变量,提高效率
onCreateViewHolder() 创建ViewHolder对象
getItemCount() 获取队列的总数
onBindViewHolder() 实现数据的绑定
3. 然后再需要使用他的地方,直接引用,直接给实例代码:
1
2
3
4
5
6
7
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initFruits() // 初始化水果数据
val layoutManager = LinearLayoutManager(this)
recyclerView.layoutManager = layoutManager
val adapter = FruitAdapter(fruitList)
recyclerView.adapter = adapter

创建了一个LinearLayoutManager对象,并将它设置到RecyclerView当中。LayoutManager用于指定RecyclerView的布局方式,这里使用的
LinearLayoutManager是线性布局的意思,可以实现和ListView类似的效果

布局管理

主要得益于RecyclerView出色的设计。ListView的布局排列是由自身去管理的,而RecyclerView则将这个工作交给了LayoutManager。LayoutManager制定了一套可扩展的布局排列接口,子类只要按照接口的规范来实现,就能定制出各种不同排列方式的布局了。

除了LinearLayoutManager之外,RecyclerView还给我们提供了GridLayoutManager和
StaggeredGridLayoutManager这两种内置的布局排列方式。GridLayoutManager可以用实现网格布局,StaggeredGridLayoutManager可以用于实现瀑布流布局
线性布局都可以参照下面的实例
给一个实例:

1
2
3
4
5
val layoutManager = StaggeredGridLayoutManager(3,
StaggeredGridLayoutManager.VERTICAL)
recyclerView.layoutManager = layoutManager
val adapter = FruitAdapter(fruitList)
recyclerView.adapter = adapter

点击事件

首先,RecyclerView并没有像Listview一样定义了点击事件。他并没有专门的点击事件。他的点击事件需要根据具体的每个子项控件去设置。而这样往往更加方便使用和易于理解。
下面是一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.girl_item, parent, false)
val viewHolder = ViewHolder(view)
//itemView表示最外层布局,也就是整个子项
viewHolder.itemView.setOnClickListener {
val position = viewHolder.adapterPosition
//获取当前点击处的序列号。
val girl = girlList[position]
//根据序列获得girl实例
Toast.makeText(parent.context,"you clicked view ${girl.girlName}",Toast.LENGTH_SHORT).show()
}
viewHolder.girlImg.setOnClickListener {
val position = viewHolder.adapterPosition
val girl = girlList[position]
Toast.makeText(parent.context,"you clicked img ${girl.girlName}",Toast.LENGTH_SHORT).show()
}
return viewHolder
}

点击事件是在onCreateViewHolder中定义的。

上述代码分别为最
外层布局和ImageView都注册了点击事件,itemView表示的就是最外层布局。RecyclerView
的强大之处也在于此,它可以轻松实现子项中任意控件或布局的点击事件。我们在两个点击事
件中先获取了用户点击的position,然后通过position拿到相应的Fruit实例,再使用Toast分
别弹出两种不同的内容以示区别