はじめに

この記事はAndroidでRecyclerViewを使おうとしたとき、かなり面倒で似たような処理が多かったので、まとめてしまおうと思ってライブラリを作った話です。
文章がめちゃくちゃですが気にしないでください

早く実装したい人へ

下のコードをまず追記します

build.gradle(Project)
allprojects {
    repositories {
        // ↓これを追記
        maven { url 'https://jitpack.io' }
    }
}
build.gradle(app)
dependencies {
    // ↓これを追記
        implementation 'com.github.peshogo:Android-Simple-RecyclerView:0.1.1'

}

これでGradleをSyncしてやればライブラリを使う準備が整います

使い方は:

(RecyclerView).initSimpleRecyclerView(
    コンテキスト(this)
    好みのデータ型のリスト,
    レイアウトのID
){ 好みのデータ型 ->
    データとレイアウトを結びつけるコード
}

使用例としては:
rviewというIDをつけたRecyclerViewをactivity_main.xmlおいていたとします
また、リスト内のレイアウトのためにcustom_row.xmlを用意して、中にlabelというIDのTextViewをおいていたとします

それをもとにかくと

MainActivity.kt
////// いろいろ
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    val items = arrayListOf(
        "Some",
        "string",
        "array"
    )

    rview.initSimpleRecyclerView(this, items, R.layout.custom_row)
    { item ->
        label.text = item
    }
}
////// いろいろ

多分これで動きます

こういうこともできます

MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    setContentView(R.layout.activity_main)

    val items = arrayListOf(
            Video("Cool Video", "this is a cool video"),
            Video("hoge hoge", "foo bar foo bar")
    )

    rview.initSimpleRecyclerView(this, items, R.layout.custom_row) {
        title.text = it.title
        description.text = it.desctiption
    }
}

data class Video(val title: String, val desctiption: String)

どういう仕組みか

いままで

いままでRecyclerViewを使おうと思ったら

  • LayoutManagerの設定
  • Adapterの作成
  • ViewHolderの作成
  • をしなくてはいけませんでした 同じ型のViewを並べるだけならもっとかんたんにかけると思いまず普通にStringの配列から作れるように作ってみました
MainActivity.kt
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContentView(R.layout.activity_main)

        val items = arrayListOf(
                "Some",
                "Text",
                "Array"
        )

            // rview は Recyclerview
        rview.layoutManager = LinearLayoutManager(this)
        rview.adapter = SimpleAdapter(items)
    }

}

class SimpleAdapter(val items: List<String>): RecyclerView.Adapter<SimpleViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SimpleViewHolder {
        val row = LayoutInflater.from(parent.context).inflate(R.layout.custom_row,parent,false)
        return SimpleViewHolder(row)
    }

    override fun onBindViewHolder(holder: SimpleViewHolder, position: Int) {
        holder.view.label.text = items[position]
    }

    override fun getItemCount(): Int {
        return items.size
    }

}

class SimpleViewHolder(val view: View): RecyclerView.ViewHolder(view)

これで動きます
でも、わかりづらい

Bindingを外に出す

SimpleAdapteronBindViewHolderを外側に出して好きにくっつけられるようにしました

また、そうするならViewも好きなのを入れられる方がいいので

class SimpleAdapter(val items: List<String>): RecyclerView.Adapter<SimpleViewHolder>() {
    /// いろいろ
    override fun onBindViewHolder(holder: SimpleViewHolder, position: Int) {
        holder.view.custom_row_title.text = items[position]
    }
    /// いろいろ
}

これにバインディング用の関数binderを追加して

class SimpleAdapter(val items: List<String>,val binder:View.(String) -> Unit): RecyclerView.Adapter<SimpleViewHolder>() {
    /// いろいろ
    override fun onBindViewHolder(holder: SimpleViewHolder, position: Int) {
        holder.view.binder(items[position])
    }
    /// いろいろ
}

こうしてViewのIDを自分で決められるようにして

class SimpleAdapter(val items: List<String>,val layout: Int, val binder:View.(String) -> Unit): RecyclerView.Adapter<SimpleViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SimpleViewHolder {
        val row = LayoutInflater.from(parent.context).inflate(layout, parent,false)
        return SimpleViewHolder(row)
    }

    override fun onBindViewHolder(holder: SimpleViewHolder, position: Int) {
        holder.view.binder(items[position])
    }
    /// いろいろ
}

こうなる

これを使って実際に実装すると

MainActivity.kt
rview.layoutManager = LinearLayoutManager(this)
rview.adapter = com.shogo.mywayofmakingapps.SimpleAdapter(items,R.layout.custom_row){
    label.text = it
}

String以外も使いたい

String でこれができるなら他の型でも行けるだろということで

class SimpleAdapter(val items: List<String>,val layout: Int, val binder:View.(String) -> Unit): RecyclerView.Adapter<SimpleViewHolder>()

これを

class SimpleAdapter<T>(val items: List<T>,val layout: Int, val binder:View.(String) -> Unit): RecyclerView.Adapter<SimpleViewHolder>()

こう変える

これでString以外も扱えるようになった。

1行で実装できるようにしたい

このままだと実装に2行必要なので1つの関数にまとめた

fun <T> RecyclerView.initSimpleRecyclerView(ctx: Activity, items: List<T>, layout: Int, binder: View.(T) -> Unit) {
    layoutManager = LinearLayoutManager(ctx)
    adapter = SimpleAdapter(items,layout,binder)
}

これでかんたんにRecyclerViewが実装できるようになった

改善していくところ

  • まだボタンを配置したときの挙動を考えられてないのでそれについて考えておきたい
  • Bindingの説明がわかりづらい

まとめ

ただのリストを作るだけならこれで結構できるんじゃないでしょうか

Github

これのレポジトリです
https://github.com/peshogo/Android-Simple-RecyclerView

説明で書いてあるコードはここです
https://github.com/peshogo/Android-Simple-RecyclerView/blob/master/simplerecyclerview/src/main/java/com/shogo/simplerecyclerview/SimpleRecyclerView.kt

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.