web-dev-qa-db-ja.com

RecyclerViewで最初に表示されるアイテムの上部オフセットを見つける

チャットメッセージを保持するアダプターを使用しているRecyclerView + LinearLayoutMangerがあります。チャットメッセージの数を最近の100件に制限しています。この問題は、古いチャットを削除すると、インデックス0が削除されたため、recyclerviewでのチャットのスクロール位置が変化することです。以下のコードを書き始めました:

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);
    }
}

最初の表示アイテムの位置の表示オフセットを取得するのは簡単だと思いました。例最初に表示されるビューが300dpで、最後の200dpのみが表示される場合、100オフセットを取得したいと思います。

このようにして、scrollToPositionWithOffset(firstVisiblePosition-1、offsetTop)を使用できます。

ここで何か不足していますか?これは簡単に理解できる問題のようですが、これをサポートするメソッドは見たことがありません。

10
tylerjroach

@黒帯。私を正しい軌道に乗せてくれてありがとう。

私が必要としたオフセットは実際にはv.getTop();だけでした。

私の本当の問題はgetChildAt()にありました。どうやらgetChildAtは、アダプターの位置ではなく、最初に表示される位置から始まります。この場合、ドキュメントの記述は不十分です。

これが結果のコードです。

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);
    }
}
12
tylerjroach