RecyclerViewとListAdapterに問題があります。
APIを介して、古いものから新しいものへと昇順でアイテムを受け取ります。
次に、submitList(items)メソッドを呼び出して、リストを更新しています。
ただし、すべてが非同期であるため、最初のアイテムを受け取った後、RecyclerViewは最初に受け取って表示したアイテムの位置に留まります。 ListAdapterクラスでは、submitList()メソッドが完了したときにコールバックがないため、追加された新しい項目の1つを更新した後にスクロールする方法が見つかりません。
ListAdapterが更新されたときにインターセプトする方法はありますか?
ListAdapterに固有ではありませんが、それでも機能するはずです。
adapter.registerAdapterDataObserver(RecyclerView.AdapterDataObserver)
を使用し、関連するonItemXXXメソッドをオーバーライドして、RecyclerViewに任意の位置までスクロールするように指示します。
例として:
adapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
(recycler_view.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(positionStart, 0)
}
})
オーバーライドするメソッドが呼び出されます:
public void onCurrentListChanged(List<T> previousList, List<T> currentList)
documentation のように:
現在の
List
が更新されたときに呼び出されます。
ListAdapter
のインラインドキュメントは次のとおりです。
このクラスは、
AsyncListDiffer
の便利なラッパーであり、アイテムのアクセスとカウントのためのアダプタの一般的なデフォルト動作を実装します。
そして後でそれは読む:
アダプターの動作をより詳細に制御したい、または特定の基本クラスを提供したい上級ユーザーは、diffイベントからアダプターの位置へのカスタムマッピングを提供する
AsyncListDiffer
を参照する必要があります。
つまり、AsyncListDiffer
のカスタム実装と組み合わせて、通常のRecyclerView.Adapter
を拡張する必要があります。 ListAdapter
ではありません(これは、便利なラッパーであり、前述の基本的な機能を備えています)。
ListAdapter
クラスをそのテンプレートとして使用できますが(拡張ではなく、手掛かりです)、結果のクラスを拡張して再利用できます。そうしないと、必要なコールバックを制御する機会がありません。
ListAdapter
ソースコードを確認しましたが、 onCurrentListChanged メソッドがあることがわかりました。
カスタムアダプタでそれをオーバーライドするだけです。リスナーにアダプターを渡してイベントをキャッチし、RecyclerViewを最初までスクロールすることもできます。
あなたのアダプター:
typealias ListChangeListener = () -> Unit
class Adapter(private val listChangeListener: ListChangeListener) : ListAdapter<Item, Adapter.ViewHolder>(Callback) {
override fun onCurrentListChanged(previousList: List<Item>, currentList: List<Item>) {
super.onCurrentListChanged(previousList, currentList)
// Call your listener here
listChangeListener()
}
// Other methods and ViewHolder class
}
アクティビティまたはフラグメントでアダプタを作成します。
recyclerView.adapter = Adapter { recyclerView.scrollToPosition(0) }