RecyclerView使用攻略

簡介

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

  1. 如果每個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é)果

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容