LoginSignup
23
22

More than 5 years have passed since last update.

RecyclerViewでセルごとに異なるレイアウトを適用する

Last updated at Posted at 2016-04-27

あんまりRecyclerView使う機会が無かったんですけど仕事で触る機会があったのでめも。

AdapterのgetItemViewTypeをオーバーライドしてデータに応じたViewTypeを返してあげるとレイアウトを使い分けることが出来ます。enum使うと綺麗に書ける感じですね。

下の例はItemEntityを継承した3種類のクラスに応じたレイアウトを表示するサンプルです。なお仕事では今のとこKotlinで書いてるのでサンプルもKotlinです。

CustomAdapter.kt
class CustomAdapter(context: Context,
                    val itemList: MutableList<ItemEntity>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    enum class ViewType(val id: Int) {
        HOGE(0) {
            override fun createViewHolder(inflater: LayoutInflater, viewGroup: ViewGroup?): RecyclerView.ViewHolder {
                // タイプに応じたViewHolderを返す
                return HogeViewHolder (inflater.inflate(R.layout.adapter_row_hoge, viewGroup, false))
            }

            override fun bindViewHolder(holder: RecyclerView.ViewHolder, itemEntity: ItemEntity) {
                holder as HogeViewHolder
                // Viewにそれぞれのデータを表示(以下略)
            }
        },
        FUGA(1) {
            override fun createViewHolder(inflater: LayoutInflater, viewGroup: ViewGroup?): RecyclerView.ViewHolder {
                return FugaViewHolder (inflater.inflate(R.layout.adapter_row_fuga, viewGroup, false))
            }

            override fun bindViewHolder(holder: RecyclerView.ViewHolder, itemEntity: ItemEntity) {
                holder as FugaViewHolder
                // Viewにそれぞれのデータを表示(以下略)
            }
        },
        PIYO(2) {
            override fun createViewHolder(inflater: LayoutInflater, viewGroup: ViewGroup?): RecyclerView.ViewHolder {
                return PiyoViewHolder (inflater.inflate(R.layout.adapter_row_piyo, viewGroup, false))
            }

            override fun bindViewHolder(holder: RecyclerView.ViewHolder, itemEntity: ItemEntity) {
                holder as PiyoViewHolder
                // Viewにそれぞれのデータを表示(以下略)
            }
        };

        companion object {
            fun forId(id: Int): ViewType {
                for (viewType: ViewType in values()) {
                    if (viewType.id == id) {
                        return viewType
                    }
                }
                throw AssertionError("no enum found for the id. you forgot to implement?")
            }
        }

        abstract fun createViewHolder(inflater: LayoutInflater, viewGroup: ViewGroup?): RecyclerView.ViewHolder

        abstract fun bindViewHolder(holder: RecyclerView.ViewHolder, itemEntity: ItemEntity)
    }

    companion object {

        // レイアウトに応じたViewHolderを作る。KotterKnifeを使うとBindが楽
        private class HogeViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
            val imageHoge: ImageView by bindView(R.id.adapter_row_hoge_image)
            val textHoge: TextView by bindView(R.id.adapter_row_hoge_text)
        }

        private class FugaViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
            val imageFuga: ImageView by bindView(R.id.adapter_row_fuga_image)
            val textFuga: TextView by bindView(R.id.adapter_row_fuga_text)
        }

        private class PiyoViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView) {
            val imagePiyo: ImageView by bindView(R.id.adapter_row_piyo_image)
            val textPiyo: TextView by bindView(R.id.adapter_row_piyo_text)
        }
    }

    private val inflater = LayoutInflater.from(context)

    // Viewを作る時に呼ばれる
    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder? {
        return ViewType.forId(viewType).createViewHolder(inflater, parent)
    }

    // ViewにデータをBindする時に呼ばれる
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) {
        holder ?: return
        val item = itemList[position]
        ViewType.forId(holder.itemViewType).bindViewHolder(holder, item)
    }

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

    // 型に応じたViewTypeを返す
    override fun getItemViewType(position: Int): Int {

        val item = itemList[position]

        return when (item) {
            is HogeItemEntity -> {
                ViewType.HOGE.id
            }
            is FugaItemEntity -> {
                ViewType.FUGA.id
            }
            is PiyoItemEntity -> {
                ViewType.PIYO.id
            }
            else -> {
                throw AssertionError("no enum found for the id. you forgot to implement?")
            }
        }
    }
}
23
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
22