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

如何为不同Fragment的RecyclerView复用同一Adapter(不同布局)?

当然可行!无需复制Adapter就能实现不同布局复用

完全没必要复制Adapter类,我们只需要给MainMarkAdapter添加一个简单的配置,就能让它适配不同Fragment里的RecyclerView布局需求~

步骤1:修改Adapter构造函数,传入布局ID

首先给Adapter的构造函数新增一个参数,用来接收当前RecyclerView需要使用的Item布局ID:

MainMarkAdapter(
    private val activity: MainActivity,
    private var listOfData: ArrayList<MainMarkModling>,
    val listener: ContentListener,
    private val itemLayoutId: Int // 新增:传入目标布局ID
) : RecyclerView.Adapter<MainMarkAdapter.ViewHolder>() {

步骤2:在onCreateViewHolder中使用传入的布局ID

修改onCreateViewHolder方法,不再硬编码布局ID,而是用我们传入的itemLayoutId来填充布局:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val view = LayoutInflater.from(parent.context).inflate(itemLayoutId, parent, false)
    return ViewHolder(view)
}

步骤3:适配不同布局的ViewHolder(关键)

如果两个布局的控件结构不同(比如控件ID、数量不一样),我们需要让ViewHolder兼容两种布局,这里推荐两种常用方式:

方式一:基于View的通用适配(适合布局差异小的情况)

如果只是部分控件ID不同,可以在ViewHolder里根据布局类型初始化控件:

class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    // 根据布局ID获取对应的标题TextView
    val titleTv: TextView = when(itemLayoutId) {
        R.layout.item_layout_fragment1 -> itemView.findViewById(R.id.tv_frag1_title)
        R.layout.item_layout_fragment2 -> itemView.findViewById(R.id.tv_frag2_title)
        else -> throw IllegalArgumentException("不支持的布局ID")
    }
    // 其他控件同理处理
}

方式二:基于ViewBinding的优雅适配(推荐)

如果布局差异较大,用ViewBinding会更清晰。先确保你已经开启了ViewBinding,然后为两个布局生成对应的Binding类(比如ItemLayoutFragment1Binding和ItemLayoutFragment2Binding),再修改ViewHolder:

class ViewHolder private constructor(
    private val binding1: ItemLayoutFragment1Binding?,
    private val binding2: ItemLayoutFragment2Binding?
) : RecyclerView.ViewHolder(
    binding1?.root ?: binding2?.root ?: throw IllegalArgumentException("无效的布局绑定")
) {
    companion object {
        // 根据布局ID创建对应的ViewHolder
        fun create(parent: ViewGroup, layoutId: Int): ViewHolder {
            return when(layoutId) {
                R.layout.item_layout_fragment1 -> {
                    val binding = ItemLayoutFragment1Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                    ViewHolder(binding, null)
                }
                R.layout.item_layout_fragment2 -> {
                    val binding = ItemLayoutFragment2Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                    ViewHolder(null, binding)
                }
                else -> throw IllegalArgumentException("不支持的布局ID")
            }
        }
    }

    // 绑定数据到布局
    fun bind(data: MainMarkModling, listener: ContentListener) {
        binding1?.let {
            it.tvFrag1Title.text = data.title
            it.root.setOnClickListener { listener.onContentClick(data) }
            // 布局1的其他绑定逻辑
        }
        binding2?.let {
            it.tvFrag2Title.text = data.title
            it.root.setOnClickListener { listener.onContentClick(data) }
            // 布局2的其他绑定逻辑
        }
    }
}

对应的,修改onCreateViewHolder和onBindViewHolder:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    return ViewHolder.create(parent, itemLayoutId)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.bind(listOfData[position], listener)
}

步骤4:在两个Fragment中初始化Adapter

最后,在两个Fragment里创建Adapter时,传入各自的布局ID即可:

Fragment1中:

val adapter = MainMarkAdapter(
    requireActivity() as MainActivity,
    fragment1DataList,
    contentListener,
    R.layout.item_layout_fragment1
)
recyclerView.adapter = adapter

Fragment2中:

val adapter = MainMarkAdapter(
    requireActivity() as MainActivity,
    fragment2DataList,
    contentListener,
    R.layout.item_layout_fragment2
)
recyclerView.adapter = adapter

这样就实现了用同一个Adapter适配不同布局的需求,后续如果要新增更多布局,只需要在ViewHolder的判断逻辑里添加对应分支即可,维护起来非常方便。

内容的提问来源于stack exchange,提问作者Nasser El Arab

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:55:59