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

如何用RecyclerView Adapter实现带头部及分组的横向列表?

Hey there! Let's tackle your two RecyclerView questions with practical, actionable code examples—they’re both super common use cases, so I’ll walk you through each step clearly.

1. Implementing a Header Inside a Horizontal RecyclerView List

To add a header to a horizontal-scrolling RecyclerView, the key is to use multiple view types in your adapter. This lets the RecyclerView distinguish between the header item and regular list items, inflating the correct layout for each.

Step 1: Define a Sealed Class for List Items

First, create a sealed class to represent both header and regular items. This makes it easy to handle different data types in the adapter:

sealed class HorizontalListItem {
    data class Header(val title: String) : HorizontalListItem()
    data class RegularItem(val content: String) : HorizontalListItem()
}

Step 2: Build the Multi-Type Adapter

Create an adapter that checks each item's type, inflates the right layout, and binds data accordingly:

class HorizontalListAdapter(private val items: List<HorizontalListItem>) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    companion object {
        private const val VIEW_TYPE_HEADER = 0
        private const val VIEW_TYPE_REGULAR = 1
    }

    // Return the correct view type for each position
    override fun getItemViewType(position: Int): Int {
        return when (items[position]) {
            is HorizontalListItem.Header -> VIEW_TYPE_HEADER
            is HorizontalListItem.RegularItem -> VIEW_TYPE_REGULAR
        }
    }

    // Inflate layouts based on view type
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        return when (viewType) {
            VIEW_TYPE_HEADER -> {
                val view = inflater.inflate(R.layout.item_horizontal_header, parent, false)
                HeaderViewHolder(view)
            }
            else -> {
                val view = inflater.inflate(R.layout.item_horizontal_regular, parent, false)
                RegularItemViewHolder(view)
            }
        }
    }

    // Bind data to the correct ViewHolder
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (val item = items[position]) {
            is HorizontalListItem.Header -> (holder as HeaderViewHolder).bind(item)
            is HorizontalListItem.RegularItem -> (holder as RegularItemViewHolder).bind(item)
        }
    }

    override fun getItemCount() = items.size

    // Header ViewHolder
    inner class HeaderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val headerTitle: TextView = itemView.findViewById(R.id.tv_header_title)

        fun bind(header: HorizontalListItem.Header) {
            headerTitle.text = header.title
        }
    }

    // Regular Item ViewHolder
    inner class RegularItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val itemContent: TextView = itemView.findViewById(R.id.tv_item_content)

        fun bind(item: HorizontalListItem.RegularItem) {
            itemContent.text = item.content
        }
    }
}

Step 3: Set Up the Horizontal RecyclerView

Finally, configure your RecyclerView to scroll horizontally and attach the adapter:

val horizontalRecyclerView = findViewById<RecyclerView>(R.id.horizontal_recycler)
val layoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
horizontalRecyclerView.layoutManager = layoutManager

// Example data list
val items = listOf(
    HorizontalListItem.Header("Featured Items"),
    HorizontalListItem.RegularItem("Item 1"),
    HorizontalListItem.RegularItem("Item 2"),
    HorizontalListItem.RegularItem("Item 3")
)
horizontalRecyclerView.adapter = HorizontalListAdapter(items)
2. Displaying Grouped Members with Horizontal RecyclerViews

For a grouped list where each group has horizontally-scrolling members, we’ll use nested RecyclerViews: a vertical outer RecyclerView for groups, and a horizontal inner RecyclerView for each group's members.

Step 1: Define Group and Member Data Classes

First, model your group and member data:

data class Group(val groupName: String, val members: List<Member>)
data class Member(val name: String, val avatarResId: Int)

Step 2: Build the Outer Vertical Adapter (for Groups)

This adapter handles each group, including initializing the inner horizontal RecyclerView:

class GroupListAdapter(private val groups: List<Group>) : RecyclerView.Adapter<GroupListAdapter.GroupViewHolder>() {

    inner class GroupViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val groupNameTv: TextView = itemView.findViewById(R.id.tv_group_name)
        private val memberRecyclerView: RecyclerView = itemView.findViewById(R.id.member_recycler)
        private lateinit var memberAdapter: MemberAdapter

        fun bind(group: Group) {
            groupNameTv.text = group.groupName

            // Set up the horizontal member RecyclerView
            memberAdapter = MemberAdapter(group.members)
            memberRecyclerView.layoutManager = LinearLayoutManager(itemView.context, LinearLayoutManager.HORIZONTAL, false)
            memberRecyclerView.adapter = memberAdapter
            memberRecyclerView.isNestedScrollingEnabled = false // Disable nested scrolling for smoother performance
            memberRecyclerView.addItemDecoration(HorizontalSpaceDecoration(16)) // Add spacing between members
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GroupViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_group, parent, false)
        return GroupViewHolder(view)
    }

    override fun onBindViewHolder(holder: GroupViewHolder, position: Int) {
        holder.bind(groups[position])
    }

    override fun getItemCount() = groups.size
}

Step 3: Build the Inner Horizontal Adapter (for Members)

This simple adapter handles displaying individual members:

class MemberAdapter(private val members: List<Member>) : RecyclerView.Adapter<MemberAdapter.MemberViewHolder>() {

    inner class MemberViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val avatarIv: ImageView = itemView.findViewById(R.id.iv_member_avatar)
        private val nameTv: TextView = itemView.findViewById(R.id.tv_member_name)

        fun bind(member: Member) {
            avatarIv.setImageResource(member.avatarResId)
            nameTv.text = member.name
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MemberViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_member, parent, false)
        return MemberViewHolder(view)
    }

    override fun onBindViewHolder(holder: MemberViewHolder, position: Int) {
        holder.bind(members[position])
    }

    override fun getItemCount() = members.size
}

Step 4: Add a Spacing Decoration (Optional)

To make the horizontal list look cleaner, add a custom ItemDecoration for spacing:

class HorizontalSpaceDecoration(private val space: Int) : RecyclerView.ItemDecoration() {
    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        outRect.right = space
        // Add left space to the first item
        if (parent.getChildAdapterPosition(view) == 0) {
            outRect.left = space
        }
    }
}

Step 5: Set Up the Outer Vertical RecyclerView

Finally, configure the outer RecyclerView to display groups vertically:

val groupRecyclerView = findViewById<RecyclerView>(R.id.group_recycler)
groupRecyclerView.layoutManager = LinearLayoutManager(this)

// Example group data
val groups = listOf(
    Group("Team A", listOf(Member("Alice", R.drawable.avatar_alice), Member("Bob", R.drawable.avatar_bob))),
    Group("Team B", listOf(Member("Charlie", R.drawable.avatar_charlie), Member("Diana", R.drawable.avatar_diana)))
)
groupRecyclerView.adapter = GroupListAdapter(groups)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:13:45