iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 26
1

前言

RecyclerView 運用來 View 展示 像是 ArrayList 或是 MutableList 這種集合
將多筆數據視覺化 , 可以讓我們很清楚所有數據 , 像是 Line 的聊天訊息 , 抑或是收藏
清單 , 都可以運用 RecyclerView 來完成。

設置 layout

RecyclerView 最好不要自定義高度 , 最好能 match_parent 或 wrap_content


<?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/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

設置 itemview layout

記得 ViewGroup 高度(下面是 constraintlayout) 一定要 wrap_content 哦


<?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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#FFFFFF">

    <TextView
        android:id="@+id/num_text"
        android:layout_width="130dp"
        android:layout_height="85dp"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:layout_marginStart="116dp"
        android:layout_marginLeft="116dp"
        android:gravity="center|center_vertical"
        android:text="1"
        android:textColor="@android:color/black"
        android:textSize="30sp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Activity

  1. 定義要展示的數據 , 前面有提到RecyclerView 是用來展示多筆數據的 , 既然如此,一定要有數據讓他呈現
    如果沒有數據 RecyclerView 會是空白的狀態。

  2. 建立Adapter ,Adapter 負責 管理所有 Recyclerview 的 View ,

  3. 將所有數據加入集合

  4. Adapter 內會定義一個變數 , 在 update 方法中 我們會讓裡面定義好的變數指向外面的集合物件(數據),在執行 notifyDataSetChanged() , 通知畫面做變更 。 如果沒通知畫面做變更 , 並重新繪製我們 RecyclerView , 就算數據是非空的狀態 , 畫面上仍然會保持空白的狀態 。

  5. 將我們設定好的 Adapter 傳遞給 RecyclerView adapter 變數, 並將 LinearLayoutManager (要傳入 Context) , 傳遞給 RecyclerView layoutManager


class MainActivity : AppCompatActivity() {


    // 1 )
    val list = mutableListOf<Int>()
   // 2 )
    val this_adapter = Adapter(this)


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

         setList()

        initRecyclerView()

    }
    
    
    
    fun  setList() {
    
    // 3 )

        for(i in 0 .. 75){

            list.add(i)

        }
        
    // 4 )    

        this_adapter.update(list)

    }
    
    
    // 5)


    fun initRecyclerView(){


        recyclerview.apply{

          adapter = this_adapter

          layoutManager = LinearLayoutManager(this@MainActivity)

        }

    }

 


}



設置 Adapter

  1. Adapter 傳遞 Context 給他 , Context 在 onCreateViewHolder 會用到

  2. 在這裡處理 Adapter 數據的做法是 ,在裡面也定義集合(innerList), 這個 Adapter 是依據 innerList的數據做畫面上的呈現 , 但只要 innerList 數據一做變動 , 必須提醒畫面數據變動了應該重畫了。

  3. 在 onCreateViewHolder 創建我們所需的 ViewHolder 物件 , 例如 RecyclerView一次可以顯示5個項目,它將創建5-6個 ViewHolder,每次調用onBindViewHolder 時 , 自動復用這些 ViewHolder 物件。

  4. getItemCount 在這裡我們可以很清楚的知道 , RecyclerView 的view呈現是依據 innerList 的數據

  5. onBindViewHolder 在這裏需要依據 數據 強制綁定 viewHolder 中的 view , 因為 Recyclerview 具有復用的View 的機制 , 如果沒有依據數據去強制綁定 view , 你只要改動一個 view , 例如 checkbox 的點選 , 你會發現往下滑時 , 接下來好幾個 view 都會是 被打勾的狀態

  6. ViewHolder 顧名思義 , 是裝 View 的容器 , 在 調用 OnBindViewHolder 時 , 將數據 與 這個位置的 viewHolder 所裝的 View 繫結在一起 。

  7. 自定義 update 方法 , 在前面有小小提到 , 目的是當數據做變動時 , 讓 innerList 指向新數據物件 , 在這裏是一個 mutablelist , 讓 innerList 指向新數據 的 mutablelist , 當 innerList 變動時要記得調用 notifyDataSetChanged() 提醒 View 數據改變了, 需要重畫


class Adapter(var ct:Context) :RecyclerView.Adapter<Adapter.ViewHolder>() {

    var innerList = mutableListOf<Int>()

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Adapter.ViewHolder {

        val view = LayoutInflater.from(ct).inflate(R.layout.itemview,parent,false)

        return  ViewHolder(view)

    }

    override fun getItemCount(): Int  = innerList.size

    override fun onBindViewHolder(holder: Adapter.ViewHolder, position: Int) {

        holder.setUI(innerList[position])

    }

    inner class ViewHolder(view: View):RecyclerView.ViewHolder(view){

        val num_text = view.num_text

        fun setUI(number:Int){

            num_text.text = number.toString()

        }


    }

    fun update(list:MutableList<Int>){

        innerList = list

        notifyDataSetChanged()

    }

 
}


上一篇
[ Day 25 ] FireBase 初體驗 Part 2 - Firebase Authentication
下一篇
[Day 27] RecyclerView 下 - itmetouchhelper
系列文
Android 菜鳥村-開發基礎 30篇32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言