【问题标题】:How to add a default static item at the top in a RecyclerView in Kotlin?如何在 Kotlin 的 RecyclerView 顶部添加默认静态项?
【发布时间】:2023-03-03 10:18:01
【问题描述】:

我想让一个项目始终出现在RecyclerView 的顶部。我正在从Firestore 获取数据并将它们显示在RecyclerView 中。我想要的是一个出现在列表顶部的项目,然后显示从Firestore 获取的项目。我该怎么做?

以下是我的适配器。

open class CategoryListAdapter(private val context: Context, private var list: ArrayList<Categories>)
    : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private var onClickListener: OnClickListener? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return MyViewHolder(
            BottomsheetCategoryListLayoutBinding.inflate(
                LayoutInflater.from(
                    parent.context
                ), parent, false
            )
        )
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val model = list[position]

        if (holder is MyViewHolder) {

            GlideLoader(context).loadPicture(model.category_image, holder.binding.ivCategoryImage)
            holder.binding.tvCategoryName.text=model.category_name
        }

        holder.itemView.setOnClickListener {
            if (onClickListener != null) {
                onClickListener!!.onClick(position, model)
            }
        }
    }

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

    fun setOnClickListener(onClickListener: OnClickListener) {
        this.onClickListener = onClickListener
    }

    interface OnClickListener{
        fun onClick(position: Int, category: Categories)
    }

    private class MyViewHolder(val binding: BottomsheetCategoryListLayoutBinding) : RecyclerView.ViewHolder(binding.root)

}

【问题讨论】:

标签: android kotlin android-recyclerview


【解决方案1】:

您可以将 ConcatAdapter 用作explained here

或者您可以创建一个处理多种类型行的适配器。我更喜欢这样做,因为它可以灵活地让子标题移动到列表中的不同位置。

创建一个密封接口来表示任一类型的行项(标题或您的 Categories 类)。

sealed interface CategoriesListItem

// For now we can use a singleton object. If you have non-static data 
// to be placed in the header, you'll need a class so you can hold that 
// data and bind it in `onBindViewHolder`.
object: CategoriesHeader: CategoriesListItem

// Your existing Categories class, now implementing the sealed interface:
data class Categories(/*...*/): CategoriesListItem

让您的列表类型为&lt;CategoriesListItem&gt; 而不是&lt;Categories&gt;,并将CategoriesHeader 作为列表中的第一项。

目前看起来您在适配器中使用了一个可变列表。我建议切换到 ListAdapter,每次发生更改时,您都可以使用新的 List 实例调用 submitList,它可以有效地为您的更改设置动画。进行此切换时,您需要将CategoriesHeader 作为每个列表中的第一项。

在您的适配器中,覆盖getItemViewType(),您可以使用常量 Ints 区分这两种类型的行。 onCreateViewHolderonBindViewHolder 应该更新以处理正在创建/绑定的行类型。

class CategoryListAdapter(private val context: Context, private var list: ArrayList<CategoriesListItem>)
    : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    companion object {
        const val VIEW_TYPE_HEADER = 0
        const val VIEW_TYPE_CATEGORIES = 1
    }

    private var onClickListener: OnClickListener? = null

    override fun getItemViewType(position: Int) = when (list[position) {
        CategoriesHeader -> VIEW_TYPE_HEADER 
        is Categories -> VIEW_TYPE_CATEGORIES 
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder = when (viewType) {
        VIEW_TYPE_HEADER -> MyHeaderViewHolder( /* ... */ )
        VIEW_TYPE_CATEGORIES -> MyViewHolder(
            BottomsheetCategoryListLayoutBinding.inflate(
                LayoutInflater.from(
                    parent.context
                ), parent, false
            )
        )
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val viewType = getItemViewType(position)
        if (viewType == VIEW_TYPE_HEADER) {
            return // assuming there's no specific data to put in the header
        }
 
        val model = list[position]
        
        if (holder is MyViewHolder) {

            GlideLoader(context).loadPicture(model.category_image, holder.binding.ivCategoryImage)
            holder.binding.tvCategoryName.text=model.category_name
        }

        holder.itemView.setOnClickListener {
            if (onClickListener != null) {
                onClickListener!!.onClick(position, model)
            }
        }
    }

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

    fun setOnClickListener(onClickListener: OnClickListener) {
        this.onClickListener = onClickListener
    }

    interface OnClickListener{
        fun onClick(position: Int, category: Categories)
    }

    private class MyHeaderViewHolder(val binding: SomeHeaderViewBinding) : RecyclerView.ViewHolder(binding.root)

    private class MyViewHolder(val binding: BottomsheetCategoryListLayoutBinding) : RecyclerView.ViewHolder(binding.root)

}

【讨论】:

    猜你喜欢
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    • 2016-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-11
    • 1970-01-01
    相关资源
    最近更新 更多