diadia

興味があることをやってみる。自分のメモを残しておきます。

RecyclerViewについて

RecyclerViewはなんのためにあるのか?

参考:

https://ithelp.ithome.com.tw/articles/10203735 https://developer.android.com/guide/topics/ui/layout/recyclerview

RecyclerViewは多量のリストデータセットを表示するためにあるようだ。

リサイクラービューで必要な要素

ViewHolderが必要らしい。これが何であるかわかっていない。
ただViewHolderはreturnさせる対象であることがわかった。onCreateViewHolderをオーバーライドしてViewHolderをリターンする。

RecyclerView.ViewHolderを継承して作るクラスには、作成したテンプレートに対応する変数を定義する。ちなみにViewHolderは、ViewHolder.ktみたいな形で定義するのが一般的なようだ。
参考:
https://qiita.com/Todate/items/297bc3e4d0f3d2477ed3#viewholder%E3%82%92%E4%BD%9C%E6%88%90
https://qiita.com/saiki-ii/items/78ed73134784f3e5db7e#2viewholder%E3%82%92%E4%BD%9C%E3%82%8B

RecyclerView自体の表示は、指定したレイアウトマネージャーから提供されるビューを使用する。(LinearLayoutManager, GridLayoutManager)
mainRecyclerView.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)

ビューホルダーがコンテンツ表示を担当する。

ビューホルダー オブジェクトはアダプターによって管理されます。ビューホルダーオブジェクトはアダプターによって生成され、アダプターによってビューホルダーのデータバインドも行われる。バインドは、アダプターの onBindViewHolder() メソッドを呼び出すことによって行います。

まとめ

onCreate上にrecyclerviewオブジェクトを取得し、applyメソッドを実施する。するとrecyclerviewを起動させることができる。

override fun onCreate{

var recyclerview = findViewById<RecyclerView>(R.id.my_recycler_view).apply


}

applyについてはこれがわかりやすいい。
参考:https://qiita.com/wakwak/items/7f576b4dbada0995f069
クラスのインスタンス生成するときに属性を設定したい場合がある。この時に"インスタンス.属性=属性値"としなくても設定できるものだと理解した。今はオブジェクト生成時に属性値を定めるためにあると思われる。

実装の概要

とりあえず、onCreateメソッドのところにRecyclerViewオブジェクトを取得する。このrecyclerViewオブジェクトを設定する際にrecyceler.Adapterオブジェクトを継承したクラスのインスタンスを生成する。

Adapterクラスでは4つのことを決める。

  1. viewHolderクラスを継承したクラスの定義
  2. onCreateViewHolderメソッドのオーバーライド
  3. onBindViewHolderメソッドのオーバーライド
  4. getItemCountメソッドのオーバーライド

各メソッドで記述することは以下の通りである。

onCreateViewHolderでは、使いたいレイアウトをインフレイトする。インフレイトしたオブジェクトを引数にViewHolderインスタンスを生成しそれを戻り値とする。 onBindViewHolderメソッドでは、生成したViewholderインスタンスとデータの繋がり方を設定する。

具体的な例

表示する内容は一つのリストに、画像とタイトルと詳細を表示する。 まずレイアウトファイルを作成する。レイアウトファイルには、RecyclerViewが記述された親レイアウトファイル(activity_main.xml)とrecyclerviewの内容である子レイアウトファイル(list_item.xml)がある。

...activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>
...list_item.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">


    <ImageView
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:src="@drawable/default_item"/>


    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <TextView
            android:id="@+id/row_title"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="0.5"
            android:text="タイトルを表示" />

        <TextView
            android:id="@+id/row_detail"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="0.5"
            android:text="詳細情報を表示" />


    </LinearLayout>

onCreateメソッドでrecyclerViewオブジェクトを取得するコードを記述する。

...MainActivity.kt

package com.example.practice_recycler_view

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

class MainActivity : AppCompatActivity() {

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

        // CreateDataset()ファンクションでデータを生成する
        val myDataset = createDataset()

        // recyclerviewオブジェクトのapplyの要素の一つを生成する
        var viewManager = LinearLayoutManager(this)
        // recyclerviewオブジェクトのapplyの要素の一つを生成する
        var viewAdapter = MyAdapter(myDataset)

        //recyclerviewを取得
        var recyclerView = findViewById<recyclerview>(R.id.my_recycler_view).apply {
            // use this setting to improve performance if you know that changes
            // in content do not change the layout size of the RecyclerView
            setHasFixedSize(true)

            // use a linear layout manager
            layoutManager = viewManager

            // specify an viewAdapter (see also next example)
            adapter = viewAdapter
        }
    }    
    
</recyclerview>

viewHolderクラスを定義する。当該クラスはRecyclerView.Adapterクラスを継承した中で定義を行う。

...MainActivity.ky


    // MyAdapterに渡す引数は実際表示するデータである。
    // 継承するAdapterのタイプにはViewHolderを記述する。
    class MyAdapter(private val myDataset: List&lt;RowModel&gt;) :
        RecyclerView.Adapter&lt;MyAdapter.MyViewHolder&gt;() {


        // viewHolderを定義する
        class MyViewHolder(val view: View) : RecyclerView.ViewHolder(view){
            val row_title  = view.findViewById&lt;TextView&gt;(R.id.row_title)
            val row_detail = view.findViewById&lt;TextView&gt;(R.id.row_detail)
        }

onCreateViewHolderメソッドを記述する。当該メソッドはRecyclerView.Adapterクラスを継承した中でオーバーライドを行う。

...MainActivity.kt

        override fun onCreateViewHolder(parent: ViewGroup,
                                        viewType: Int): MyAdapter.MyViewHolder {
            // レイアウトファイルをインフレイトしてオブジェクトを生成する。
            // 第一引数はインフレイトしたいレイアウトファイル
            val rowView = LayoutInflater.from(parent.context)
                .inflate(R.layout.list_item, parent, false)

            // 定義したViewHolderにインフレイトしたオブジェクトを引数として渡す。
            // 戻り値はMyViewHolderインスタンスである。
            return MyViewHolder(rowView)    
        }

onBindViewHolderメソッドを記述する。当該メソッドはRecyclerView.Adapterクラスを継承した中でオーバーライドを行う。

...MainActivity.kt

        // onBindViewHolderの引数は生成したMyViewHolderインスタンスである。
        // 第2引数はリスト型データの番号である。
        override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
 
            // row_titeはMyViewHolderの属性値である。
            // myDataset[position].titleは、myDatabaseの要素がRowModelであり、そのRowModelの属性値にtitleである。
            holder.row_title.text = myDataset[position].title
            // row_detailはMyViewHolderの属性値である。
            holder.row_detail.text = myDataset[position].detail
        }

getItemCountメソッドをオーバーライドする。当該メソッドはRecyclerView.Adapterクラスを継承した中でオーバーライドを行う。

override fun getItemCount() = myDataset.size

次にmuDatasetの要素そのもの(Model)について定義を行う。 この定義が終わったら、このModelを利用してリスト型データを生成する関数を生成する関数を定義する。

    class RowModel{
        var title : String  = ""
        var detail : String = ""
private fun createDataset():List<RowModel>{
    val dataList = mutableListOf<RowModel>()
    for (i in 0..49){
        var data = RowModel().apply{
            var it.title  = "タイトル番号"+i
            var it.detail = "詳細の番号" +i
        }
        dataList.add(data)
    }
    return dataList
}