使用 RecyclerView 的多视图 - Kotlin(Android) - 无法切换视图

Posted

技术标签:

【中文标题】使用 RecyclerView 的多视图 - Kotlin(Android) - 无法切换视图【英文标题】:Multiviews using RecycleView - Kotlin(Android) - Unable to switch viewholder 【发布时间】:2020-09-10 07:10:27 【问题描述】:

我已经浏览了几天来寻找我的问题的解决方案,但我很困惑,无法弄清楚问题所在。我是 android/Kotlin 的相对初学者,所以请多多包涵。

我有一个如下所示的数据类,我从静态源填充了 pid 值等。

class MyOrderList(var pid: String, var name: String, var imageUrl: String, var size: String, var description: String, val price: Int, var count: Int, var itemtotal: Int)

这个想法基本上是,如果你遍历上面的类列表,pid 通常由一个数字或一个特定的单词表示,例如“LIQUID”。所以在我的列表中,位置 0 会显示 pid = "LIQUID",而位置 1 是一个数字,比如 pid = 2。

我想创建一个 recyclerview,当它在列表中将 LIQUID 视为 pid 时,它将使用 viewholder2 及其自己的布局。否则它将使用 viewholder1 和自己的布局。

问题是我创建的 recyclerview 只显示一个视图。如果位置 0 pid 为 LIQUID,则视图持有者为 ViewHolder2,即使对于列表中 PID 不再为 LIQUID 的后续项目也是如此。简而言之,位置 0 上的 pid 值将决定整个列表的视图。

我还在摸索RecyclerView的曲折,还是没有完全理解。

请看下面的sn-p。

======================

class MyOrderCart(var myOrder: MutableList, var mymutablelist: MutableList): RecyclerView.Adapter()

inner class ViewHolder1(itemView: View) : RecyclerView.ViewHolder(itemView) 

    fun bindView1(mycartlist: MyOrderList)
        itemView.nameView.text = mycartlist.name
        itemView.sizeView.text = "Size: $mycartlist.size"

        var iprice = mycartlist.price
        itemView.priceView.text = "Price: $iprice"
        var icount = mycartlist.count
        itemView.countView.text = "Count: $icount"
        var itotal = mycartlist.itemtotal
        itemView.itemtotalView.text = "Subtotal: $itotal"

        var image_checkout = itemView.findViewById(R.id.image_checkout) as ImageView
        var checkout_deletebutton = itemView.findViewById(R.id.checkout_deletebutton) as ImageButton
        var checkout_editcount = itemView.findViewById(R.id.checkout_editcount) as ImageButton
        var mytime = System.currentTimeMillis()

        try 
            Glide.with(image_checkout.getContext()).load(mycartlist.imageUrl)
                .signature(ObjectKey(mytime)).into(image_checkout)
                .clearOnDetach()
         finally 
            image_checkout.setImageResource(R.drawable.noimage)
        
    

inner class ViewHolder2(itemView: View) : RecyclerView.ViewHolder(itemView) 
    fun bindView2(mycartlist: MyOrderList)
        itemView.checkout_inside_textview.text = mycartlist.pid
    


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder 
    var myorderviewtype = myOrder.get(viewType)
        return when (myorderviewtype.pid) 
            "LIQUOR" -> 
                ViewHolder2(
                    LayoutInflater.from(parent.context)
                        .inflate(R.layout.insidecheckout_label, parent, false)
                )
            
            "NOODLES" -> 
                ViewHolder2(
                    LayoutInflater.from(parent.context)
                        .inflate(R.layout.insidecheckout_label, parent, false)
                )
            
            else -> 
                ViewHolder1(
                    LayoutInflater.from(parent.context)
                        .inflate(R.layout.layout_insidecheckout, parent, false)
                )
            
        


override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) 
    val gsonRaw = GsonBuilder().create()
    var pos = viewHolder.getAdapterPosition()
    var mycartlist: MyOrderList = myOrder.get(position)
    when (viewHolder) 
        is ViewHolder2 -> 
            val liquorviewHolder = viewHolder as ViewHolder2
            liquorviewHolder.bindView2(mycartlist)
        
        is ViewHolder1 -> 
            val liquorviewHolder = viewHolder as ViewHolder1
            liquorviewHolder.bindView1(mycartlist)
        
    


【问题讨论】:

【参考方案1】:

您还没有覆盖 getItemViewType 方法。试试下面的代码。

    override fun getItemViewType(position: Int): Int 
    return myOrder.get(position).pid


override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder 
    return when (viewType) 
        "LIQUOR" -> 
            ViewHolder2(
                    LayoutInflater.from(parent.context)
                            .inflate(R.layout.insidecheckout_label, parent, false)
            )
        
        "NOODLES" -> 
            ViewHolder2(
                    LayoutInflater.from(parent.context)
                            .inflate(R.layout.insidecheckout_label, parent, false)
            )
        
        else -> 
            ViewHolder1(
                    LayoutInflater.from(parent.context)
                            .inflate(R.layout.layout_insidecheckout, parent, false)
            )
        
    

由于您没有使用 getItemViewType 发送 viewType,因此您在 onCreateViewHolder 中总是得到 0。

【讨论】:

谢谢阿什特。 getItemViewType 需要 Int 作为返回类型。但是你的意见对我帮助很大。谢谢!!! pid 不是一个 int 变量吗?【参考方案2】:

在您的适配器类中,您需要覆盖getItemViewType 方法。 像这样:

override fun getItemViewType(position: Int): Int 
    // return view type according to position
    // get your pid using position
    // return 0 for "LIQUOR", 1 for "NOODLES" and 2 for anything else
    // you have to return an integer value only, according to the method signature

然后在 onCreateViewHolder 方法中,使用 int 类型的 viewType 参数来膨胀所需的视图:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder 

    return when (viewType) 
        0 -> 
            ViewHolder2(
                LayoutInflater.from(parent.context)
                    .inflate(R.layout.insidecheckout_label, parent, false)
            )
        
        1 -> 
            ViewHolder2(
                LayoutInflater.from(parent.context)
                    .inflate(R.layout.insidecheckout_label, parent, false)
            )
        
        else -> 
            ViewHolder1(
                LayoutInflater.from(parent.context)
                    .inflate(R.layout.layout_insidecheckout, parent, false)
            )
        
    

【讨论】:

嗨,范什。你的推荐有效!!!我做了以下并修改了 oncreateviewholder 以预测 viewtype 值。覆盖 fun getItemViewType(position: Int): Int var mycartlist: MyOrderList = myOrder.get(position) when(mycartlist.pid) "LIQUOR" -> return 1 "NOODLES" -> return 2 else -> 返回 0

以上是关于使用 RecyclerView 的多视图 - Kotlin(Android) - 无法切换视图的主要内容,如果未能解决你的问题,请参考以下文章

Android RecyclerView 项目在滚动时随机播放

ko 视图模型在 js 上更新但未在 html 视图中显示

如何将 ko.validation 错误与相关的视图模型字段名称联系在一起

为啥 ko.ObservableArray 中的替换值没有更新我的视图?

RecyclerView使用详解

以编程方式添加视图与使用 recyclerView 有啥区别?