Finding top offset of first visible item in a RecyclerView
Asked Answered
C

1

12

I have a RecyclerView + LinearLayoutManger which is using an adapter that holds chat messages. I limit the number of chat messages to the most 100 recent. This issue is that when I remove the older chats, the scroll position of the chats in the recyclerview changes because index 0 was removed. I began writing the code below:

int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
View v = layoutManager.getChildAt(firstVisiblePosition);
if (firstVisiblePosition > 0 && v != null) {
    int offsetTop = //need to get the view offset here;
    chatAdapter.notifyDataSetChanged();

    if (firstVisiblePosition - 1 >= 0 && chatAdapter.getItemCount() > 0) {
        layoutManager.scrollToPositionWithOffset(firstVisiblePosition - 1, offsetTop);
    }
}

I thought it would be easy to get the visible offset of the first visible item position. Ex. if the first visible view is 300dp but only the last 200dp is visible, I would like to get the 100 offset.

This way I could use scrollToPositionWithOffset(firstVisiblePosition - 1, offsetTop).

Am I missing something here? This seems like it would be an easy problem to figure out, but I haven't seen any methods that would support this.

Commination answered 1/12, 2015 at 19:27 Comment(2)
did you try with v.getHeight() - v.getTop()Meakem
I'll look into it further. I think v.getTop() gets the y coordinate of the total scroll height, not relative to the location of the recyclerview top itself.Commination
C
14

@Blackbelt. Thank you for getting me on the right track.

The offset that I needed was actually just v.getTop();

My real problem was in getChildAt(). Apparently getChildAt begins at the first visible position, not at the position of the adapter. The documentation is poorly written in this case.

Here is the resulting code.

int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
View v = layoutManager.getChildAt(0);
if (firstVisiblePosition > 0 && v != null) {
    int offsetTop = v.getTop();
    chatAdapter.notifyDataSetChanged();

    if (firstVisiblePosition - 1 >= 0 && chatAdapter.getItemCount() > 0) {
         layoutManager.scrollToPositionWithOffset(firstVisiblePosition - 1, offsetTop);
    }
}
Commination answered 1/12, 2015 at 20:39 Comment(1)
You can use View v = layoutManager.findViewByPosition(position)Yonita

© 2022 - 2024 — McMap. All rights reserved.