簡介
RecyclerView是什么?
- RecycleView是一個用于在有限的窗口中展示大量數(shù)據(jù)集的控件
- Google用于代替ListView的滑動組件
RecyclerView的優(yōu)缺點
優(yōu)點
由名字可知,RecyclerView,回收復(fù)用視圖,RecyclerView只管回收與復(fù)用View,其他的你可以自己去設(shè)置,一個類實現(xiàn)一個功能,高度的解耦

缺點
RecyclerView實現(xiàn)控制點擊、長按事件較為麻煩,需要自己寫
詳解
一、知識儲備
RecylerView高度解耦,一個類實現(xiàn)一塊功能,使用前需要先了解一下類
-
LayoutManager
布局管理器,默認(rèn)提供LinearLayoutManager、GridLayoutManager、StaggeredGridLayoutManager三大類,分別可以實現(xiàn)ListView,GridView以及流式布局的列表效果。
-
Adapter
適配器,適配數(shù)據(jù)如何顯示,通過實現(xiàn)RecyclerView.Adapter接口中的方法實現(xiàn)數(shù)據(jù)的適配。
同時,RecyclerView的適配器強制要求了我們必須要用Viewholder,讓性能得到優(yōu)化,而且getView方法不需自己寫,我們只需要寫好Viewholder,View的復(fù)用已經(jīng)封裝好了。
-
ItemDecoration
Decoration 的英文意思是裝飾物的意思,引申到這里來,肯定也是與 RecyclerView 的界面裝飾有關(guān)。我們常見的就是分割線和item間距的配置
-
SnapHelper
如果每個Item顯示?屏、按?來顯示,可以通過設(shè)置此類快速實現(xiàn),有SnapHelper 、LinearSnapHelper 、PagerSnapHelper這三個類
-
itemAnimator
這個類可以實現(xiàn)item的增刪動畫,不想設(shè)置的話它的默認(rèn)效果也挺好的。
二、使用步驟
RecyclerView的使用步驟大致是這樣固定的,效果和性能在于細節(jié)
使用步驟:
1、創(chuàng)建RecyclerView 通常在xml中配置
2、代碼中設(shè)置屬性
? 確定布局樣式 設(shè)置layoutManager
? 確定數(shù)據(jù)源
3、定義一個Adapter實現(xiàn)RecyclerView.Adapter接口中的方法
?RecyclerView通過接口中的方法訪問數(shù)據(jù)
??a、創(chuàng)建一個類繼承于 RecyclerView.ViewHolder,重復(fù)利用
?? b、重寫adapter的接口方法
???getItemCount:確定RecyclerView中有多少個item
??? onCreateViewHolder:確定每個item的具體視圖
???onBindViewHolder:綁定視圖
4、設(shè)置item裝飾器 addItemDecoration
? 1)系統(tǒng)提供的 DividerItemDecoration 分割線
? 2)??創(chuàng)建?個類繼承于ItemDecoration 重寫onDraw或者onDrawOver、getItemOffset
- 如果每個Item顯示?屏 按?來顯示 SnapHelper 、LinearSnapHelper 、 PagerSnapHelper
三、使用案例
1、創(chuàng)建一個工程,在xml中加入RecyclerView控件(最新版RecyclerView在androidx包,老版本為v7包),本案例直接在activity_main.xml中加
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/mRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
2、在MainActivity中獲取RecyclerView控件,設(shè)置相關(guān)屬性
由于AndroidStudio升級到4.1后,kotlin不默認(rèn)使用id獲取控件,而是建議用ViewBinding綁定控件,在此使用ViewBinding(即運行時為activity_main.xml生成一個ActivityMainBinding的類)
class MainActivity : AppCompatActivity() {
/** AS4.1版本不默認(rèn)支持用id訪問控件 這里使用ViewBinding
* 如果想要繼續(xù)使用id訪問控件 模塊的build.gradle中加入 id 'kotlin-android-extensions'
* 這里默認(rèn)生成了ActivityMainBinding的類,此類關(guān)聯(lián)了activity_main.xml
*/
private var mBinding: ActivityMainBinding? = null
private val dataSource:ArrayList<Int> = ArrayList()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//綁定xml
mBinding = ActivityMainBinding.inflate(LayoutInflater.from(this))
//設(shè)置為xml的根容器 即ConstraintLayout
setContentView(mBinding?.root)
//設(shè)置布局樣式
// mBinding?.mRecyclerView?.layoutManager = LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false)
mBinding?.mRecyclerView?.layoutManager = StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL)
//確定數(shù)據(jù)源
for (i in 1..10){
if (i % 2 == 0){
dataSource.add(R.drawable.sy)
}else{
dataSource.add(R.drawable.gl)
}
}
//設(shè)置適配器
mBinding?.mRecyclerView?.adapter = MainAdapter(dataSource)
//輔助類 使得滑動如翻頁
PagerSnapHelper().attachToRecyclerView(mBinding?.mRecyclerView)
//設(shè)置裝飾decoration 間隔、分割線等
mBinding?.mRecyclerView?.addItemDecoration(MyItemDecoration())
}
}
3、創(chuàng)建item顯示樣式的xml
即用xml編寫RecyclerView的每一個item顯示需要的控件和布局,在adapter中進行解析和數(shù)據(jù)綁定
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content">
<ImageView
android:id="@+id/iconImageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:scaleType="fitCenter"
android:src="@drawable/desktop1"
app:layout_constraintDimensionRatio="16:9"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/titleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:text="銀河以北,吾彥最美"
android:textColor="#000"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/iconImageView" />
</androidx.constraintlayout.widget.ConstraintLayout>
4、創(chuàng)建一個類繼承于RecyclerView.Adapter
通過實現(xiàn)其接口方法對RecyclerView進行適配,解釋請看代碼注釋
class MainAdapter: RecyclerView.Adapter<MainAdapter.MyViewHold> {
lateinit var imageDataSource:ArrayList<Int>
constructor(images:ArrayList<Int>){
this.imageDataSource = images
}
//確定每個item的具體視圖
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHold {
//獲取xml的視圖 xml-》View
//如果知道一個View 就可以通過這個view獲取其上下文content
val layoutInflater = LayoutInflater.from(parent.context)
val itemView = layoutInflater.inflate(R.layout.main_recycler_item,parent,false)
// val itemView = layoutInflater.inflate(R.layout.card_item,parent,false)
return MyViewHold(itemView)
}
//視圖解析出來之后 需不需要將數(shù)據(jù)綁定到上面
@SuppressLint("WrongConstant")
override fun onBindViewHolder(holder: MyViewHold, position: Int) {
holder.iconImageView.setImageResource(imageDataSource[position])
holder.titleView.text = if (position%2 ==0) "銀河以北,吾彥最美" else "銀河以南,為彥而燃"
//item點擊事件
holder.iconImageView.setOnClickListener{
Toast.makeText(holder.iconImageView.context,holder.titleView.text,1000).show()
}
}
//確定RecyclerView中有多少個 Item
override fun getItemCount(): Int {
return imageDataSource.size
}
//傳遞來的view 是RecyclerView顯示的每一個item
class MyViewHold: RecyclerView.ViewHolder{
lateinit var titleView:TextView
lateinit var iconImageView: ImageView
constructor(itemView:View):super(itemView){
titleView = itemView.findViewById(R.id.titleTextView)
iconImageView = itemView.findViewById(R.id.iconImageView)
}
}
}
5、設(shè)置itemDecoration
創(chuàng)建一個類繼承于RecyclerView.ItemDecoration,設(shè)置間隔的話實現(xiàn)其getItemOffsets方法,再到MainActivity中設(shè)置recyclerView的itemDecoration
class MyItemDecoration: RecyclerView.ItemDecoration() {
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
outRect.set(10,10,10,10)
}
}
6、設(shè)置SnapHelper,翻頁效果等
//輔助類 使得滑動如翻頁
PagerSnapHelper().attachToRecyclerView(mBinding?.mRecyclerView)
7、設(shè)置點擊事件
在onCreateViewHolder中設(shè)置
//確定每個item的具體視圖
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHold {
//獲取xml的視圖 xml-》View
//如果知道一個View 就可以通過這個view獲取其上下文content
val layoutInflater = LayoutInflater.from(parent.context)
val itemView = layoutInflater.inflate(R.layout.main_recycler_item,parent,false)
// val itemView = layoutInflater.inflate(R.layout.card_item,parent,false)
itemView.setOnClickListener{
//點擊事件
}
return MyViewHold(itemView)
}
也可以在onBindViewHolder中對控件設(shè)置點擊事件
//視圖解析出來之后 需不需要將數(shù)據(jù)綁定到上面
@SuppressLint("WrongConstant")
override fun onBindViewHolder(holder: MyViewHold, position: Int) {
holder.iconImageView.setImageResource(imageDataSource[position])
holder.titleView.text = if (position%2 ==0) "銀河以北,吾彥最美" else "銀河以南,為彥而燃"
holder.iconImageView.setOnClickListener{
Toast.makeText(holder.iconImageView.context,holder.titleView.text,1000).show()
}
}
四、運行結(jié)果
