Let’s scroll to the position of the posted item, which just created by a user, on the list using RecyclerView inside NestedScrollView.

Lukoh Nam
빅펄 (헤드라잇)
3 min readAug 21, 2022
Illustration by Ella Dobson

We often implement functionality such as commenting or posting using RecyclerView which has adapter is extended from ListAdapter inside a NestedScrollView. For example, a user writes a comment, sends it to a backend server and gets an updated list of comments within seconds. These may get rearranged according to the intent of the service or backend engineer. That is, it means we could receive the rearranged the list of items. How can we scroll to the correct position of list items a user just posted in RecyclerView inside NestedScrollView.

Let’s dive into it. :) Please refer to below code:

CommentReplyFragment : Function-Reply the comment

private fun postReply(info: CommentInfo, taggedUserId: String?) {
val viewModel = PostCommentViewModel.provideFactory(
postCommentViewModelFactory,Params(Query(......))
).create(PostCommentViewModel::class.java)

view?.let {
launchAndRepeatWithViewLifecycle {
viewModel.value.collectLatest { resource ->
when (resource.getStatus()) {
Status.SUCCESS -> {
resource.getData()?.let {
@Suppress("UNCHECKED_CAST")
val response =
resource.getData() as? Response

ReplyAdapter?.let { adapter ->
lifecycleScope.launch {
with(binding) {
hideSendView(this, false)
setCommentCount(++count)
}
}

taggedNickname = ""
response?.let {
it.payload.first { comment ->
info.commentId == comment.id
}?.children?.let { list ->
replied = true
adapter.isPosted = true
adapter.reply =
detectInfo.comment
adapter.submitList(list)
...
}
}
}
}
}

Status.ERROR -> {
showComment(binding, false)
showErrorPopup(resource.getMessage()!!) {}
}

Status.LOADING -> {
showComment(binding, true)
}
}
}
}
}
}

ReplyApdater : draw the received the items of list

class ReplyAdapter(
private val replyFragment: CommentReplyFragment, ...
) : ListAdapter<Comment, ReplyAdapter.ItemHolder>(CommentDiffUtil) {
private var _binding: ItemCommentBinding? = null
private val binding get() = _binding!!

internal var isPosted = false

internal var reply = ""

object CommentDiffUtil : DiffUtil.ItemCallback<Comment>() {
override fun areItemsTheSame(
oldItem: Comment, newItem: Comment): Boolean {
return oldItem.id == newItem.id
}
)
override fun areContentsTheSame(
oldItem: Comment, newItem: Comment
): Boolean {
return oldItem.content == newItem.content
}
}

override fun onCreateViewHolder(
parent: ViewGroup, viewType: Int
): ItemHolder {
val contextThemeWrapper =
ContextThemeWrapper(
replyFragment.homeActivity, R.style.AppTheme
)

_binding = null
_binding = ItemCommentBinding.inflate(
LayoutInflater.from(contextThemeWrapper),
parent,
false
)

return ItemHolder(binding)
}

@OptIn(ExperimentalTime::class)
override fun onBindViewHolder(
holder: ItemHolder, position: Int
) {
val item = getItem(position)

with(holder.binding) {
...
.
..

tvComment.post {
if (replyFragment.isAdded) {
with(replyFragment.binding) {
val params = rvReply.layoutParams

params.height = MATCH_PARENT
rvReply.layoutParams = params

if (isPosted && reply == item.content) {
vScroll.post {
rvReply.getChildAt(position)?.let {
vScroll.scrollY =
(rvReply.y + it.y).toInt()
}
}

isPosted = false
}
}
}
}

...
...

containerReport.setSafeOnClickListener {
replyFragment.lifecycleScope.launchWhenResumed {
showCommentReportDialog(
replyFragment.homeActivity,
item,
tvComment,
containerCommentCount,
likeContainer,
dislikeContainer,
containerReport
)
}
}
.... }
}

override fun onViewDetachedFromWindow(holder: ItemHolder) {
super.onViewDetachedFromWindow(holder)

_binding = null
}
....
....
....
}
CommentReplyAdapter.kt implemnted by Lukoh

Conclusion

This method would be very useful and easy for scrolling to the position of the posted item the user just created if the received list items may are rearranged.

Thank you so much for reading and I hope this article was helpful. If you have something to say to me, please leave a comment, and if this article was helpful, please share and clicks 👏.

--

--