You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio Kotlin中RecyclerView如何根据对象特征实现多类型视图——以Rick and Morty API角色状态区分卡片为例

没问题!这事儿用RecyclerView的getItemViewType()完全能搞定,我给你一步步调整代码:

第一步:定义视图类型常量 & 重写getItemViewType()

先在你的Adapter里加两个常量标记不同视图类型,然后重写getItemViewType()方法,根据角色的status返回对应类型:

class Adapter(val characterList: List<Result>): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    // 定义视图类型常量
    companion object {
        private const val VIEW_TYPE_ALIVE = 0
        private const val VIEW_TYPE_DEAD = 1
    }

    override fun getItemViewType(position: Int): Int {
        return when(characterList[position].status) {
            "Alive" -> VIEW_TYPE_ALIVE
            "Dead" -> VIEW_TYPE_DEAD
            else -> VIEW_TYPE_ALIVE // 其他状态默认用Alive的卡片
        }
    }

    // 其他方法后续修改
}

第二步:创建对应两种布局的ViewHolder

你已经有默认的carditem蓝色背景布局,假设红色背景的布局叫carditem_dead,我们需要两个ViewHolder类来分别对应:

// 对应Alive角色的默认蓝色卡片
class AliveViewHolder(container: ViewGroup) : RecyclerView.ViewHolder(
    LayoutInflater.from(container.context).inflate(R.layout.carditem, container, false)
) {
    val crdView: CardView = itemView.findViewById(R.id.cardview1)
    val profileLink: ImageView = itemView.findViewById(R.id.imgProfilePhoto)
    val txtname: TextView = itemView.findViewById(R.id.name)
    val txtlocation: TextView = itemView.findViewById(R.id.location)
    val txtstatus: TextView = itemView.findViewById(R.id.status)

    fun bind(characterItem: Result) {
        txtname.text = characterItem.name
        profileLink.load(characterItem.image)
        txtlocation.text = characterItem.location.name
        txtstatus.text = characterItem.status
    }
}

// 对应Dead角色的红色背景卡片
class DeadViewHolder(container: ViewGroup) : RecyclerView.ViewHolder(
    LayoutInflater.from(container.context).inflate(R.layout.carditem_dead, container, false)
) {
    // 注意要和你的carditem_dead布局里的控件id对应
    val crdView: CardView = itemView.findViewById(R.id.cardview_dead)
    val profileLink: ImageView = itemView.findViewById(R.id.imgProfilePhoto_dead)
    val txtname: TextView = itemView.findViewById(R.id.name_dead)
    val txtlocation: TextView = itemView.findViewById(R.id.location_dead)
    val txtstatus: TextView = itemView.findViewById(R.id.status_dead)

    fun bind(characterItem: Result) {
        txtname.text = characterItem.name
        profileLink.load(characterItem.image)
        txtlocation.text = characterItem.location.name
        txtstatus.text = characterItem.status
        // 也可以直接在这里设置背景色,不用单独布局:crdView.setCardBackgroundColor(Color.RED)
    }
}

小贴士:如果两个布局的控件id完全一致,其实可以不用写两个ViewHolder,只需要在加载布局时根据viewType选对应xml就行,但分开写更清晰,后期维护也方便。

第三步:修改Adapter的onCreateViewHolder和onBindViewHolder

让Adapter根据不同viewType创建对应ViewHolder,并绑定数据:

class Adapter(val characterList: List<Result>): RecyclerView.Adapter<RecyclerView.ViewHolder>() {
    // 上面的常量和getItemViewType方法不变

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when(viewType) {
            VIEW_TYPE_ALIVE -> AliveViewHolder(parent)
            VIEW_TYPE_DEAD -> DeadViewHolder(parent)
            else -> AliveViewHolder(parent)
        }
    }

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

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        val character = characterList[position]
        when(holder) {
            is AliveViewHolder -> holder.bind(character)
            is DeadViewHolder -> holder.bind(character)
        }
    }
}

最后检查

确保你的红色背景布局carditem_dead已创建,控件id和ViewHolder里的对应上(或者直接在DeadViewHolder里设置卡片背景色,不用额外布局)。这样运行后,Alive角色会显示蓝色默认卡片,Dead角色会显示红色专属卡片啦!

内容的提问来源于stack exchange,提问作者CSS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 21:47:30