首页 > 解决方案 > 安卓。具有多种视图类型的回收器视图

问题描述

我有 2 种视图类型(项目和 FOOTER)的 recyclerView。即使没有项目或项目大小为 1,我也需要在屏幕底部显示页脚。是否可以实施?现在我的页脚显示在最后一项之后,但我需要始终在底部显示页脚。

标签: javaandroidkotlinandroid-recyclerview

解决方案


您需要一个允许您这样做的数据结构,然后您需要视图持有者来支持它,一旦完成处理适配器上的条件流并且应该很好。

通常,在 Kotlin 中,我们使用 asealed class允许非常好的类型控制

sealed class AdapterRow {
    data class RegularItem(/*your values*/) : AdapterRow()
    data class FooterItem(/*your values*/) : AdapterRow()
    //if the footer is always the same maybe object FooterItem : AdapterRow() is more suitable

}

将密封的后代放在里面是一个很好的“技巧”,这样密封的父级就可以创建一个域名空间名称,然后你就可以这样称呼它们AdapterRow.RegularItem(...)。如果你不喜欢这样,密封类有一个约束,后代必须在同一个文件上。

然后,您需要一个视图持有者来支持每种类型(如果需要,视图持有者和布局中的视图)。在这种情况下,我们将使用抽象类来利用多态性和抽象方法

//you could use binding here and then the implementation define the binding type
abstract class BaseViewHolder(view: View) : RecyclerView.ViewHolder(view) { 
    abstract fun bind(row: AdapterRow)
}

然后孩子们:

class RegularItemViewHolder(view: View) : BaseViewHolder(view) {

    override fun bind(row: AdapterRow) {
         //validate the data you are receiving is correct
         if (row !is AdapterRow.RegularItem) return
         //do your data bindings, view findings or whatever
    }

}

通过上面你可以推断出另一个视图持有者,现在是适配器方法

getItemViewType(position: Int) {
    when(getItem(position)) {
        is AdapterRow.RegularItem -> R.layout.REGULAR_ITEM_LAYOUT
        is AdapterRow. FooterItem -> R.layout.FOOTER_ITEM_LAYOUT
    }

}

onCreateViewHolder(...) {
    return when (viewType) {
         R.layout.REGULAR_ITEM_LAYOUT -> {
             RegularItemViewHolder(...)
         }
         R.layout.FOOTER_ITEM_LAYOUT {
             //same but for footer
         }
         else -> throw RuntimeException("Unsupported view Holder)
    }

}

onBindViewHolder(...) {
    holder.bind(getItem(position))
}

数据构造部分是最后一件事,在其他地方,您的片段、视图模型等,您必须根据需要创建数据结构。举例:

fun makeRows(texts: List<String>): List<AdapterRow> {
    val rows = mutableListOf<AdapterRow>()
    texts.forEach { text ->
        //do some mapping from what ever is your source in this case strings
        AdapterRow.RegularItem(...text)
    }
    //so it doesn't matter if the source of data is empty at the end you always add the footer
    rows.add(AdapterRow.FooterItem)
}

然后只是将数据传递给适配器,如果您正在使用ListAdapter

val rows = someClass.makeRows(....)
yourAdapter.submitList(rows)

推荐阅读