1

I'm trying to implement a comment section that allows the user to post and reply to another comment.

I have a list of comments, each comment has a list of replies this list may be null if there are no replies.

At first, I thought about using two recycler views, then I saw this post that says that using 2 RecyclerViews is not the best approach.

The comment and reply share the same layout, but the reply has a margin-left of 24dp.

Problem

My problem begins on onBindViewHolder the position will go from 0 to comments + replies

For example:

A list containing 2 objects with 5 replies each, in onBindViewHolder

position = 3 would be the reply[2] of comments[0] = comments[0].reply[2]

position = 6 would be comments[1]

How can determine the comment index and reply index from the position? I feel lost here

var comments = listOf<CommentModel>()
    set(value) {
        field = value
        notifyDataSetChanged()
    }

class ViewHolder(var binding: ItemForumCommentBinding) : RecyclerView.ViewHolder(binding.root) {
   fun bind(item: CommentModel){
       binding.commentModel = item
   }

   fun bind(item: ReplyModel){
       binding.commentModel = item
       (binding.commentGuideline.layoutParams as ConstraintLayout.LayoutParams).guideBegin = 24.px
   }
 }

 override fun onBindViewHolder(holder: ViewHolder, position: Int){
     //Bind comment or reply according to the position
     //holder.bind(comments[x].replys[y]) or holder.bind(comments[x])
 }
Tiago Oliveira
  • 1,582
  • 1
  • 16
  • 31

1 Answers1

2

You can create some list that contains both comment and replies, and use it as single data provider for the list, e.g.:

var commentsWithReplies = mutableListOf<Any>()

var comments = listOf<CommentModel>()
    set(value) {
        field = value
        commentsWithReplies.clear()
        value.forEach {
            commentsWithReplies.add(it)
            commentsWithReplies.addAll(it.replies)
        }
        notifyDataSetChanged()
    }

Then in getItemCount:

override fun getItemCount(): Int = commentsWithReplies.size

and in onBindViewHolder:

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
     val item = commentsWithReplies[position]
     if (item is CommentModel) {
       holder.bind(commentsWithReplies[position] as CommentModel)
     } else if (item is ReplyModel) {
       holder.bind(commentsWithReplies[position] as ReplyModel)
     }
}

P.S.

Of course, it's the very simple solution. You can refactor it (at least, use custom interface, not Any for the generic list)

S-Sh
  • 3,564
  • 3
  • 15
  • 19