【发布时间】:2021-06-04 09:13:26
【问题描述】:
所以基本上这个问题已经存在于网络上:如何让我的RecyclerView 滚动到底部并显示新项目?几乎总能找到答案:添加stackFromEnd=true 或reverseLayout=true。就我而言,我尝试了两者的所有可能组合,但它没有奏效。我还看到了这样的解决方案:
viewAdapter.registerAdapterDataObserver(object : AdapterDataObserver() {
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
//(layoutManager as? LinearLayoutManager)?.scrollToPositionWithOffset(viewAdapter.itemCount - 1, 0) or
//(layoutManager as? LinearLayoutManager)?.smoothScrollToPosition(this@ChatMessagesList, null, viewAdapter.itemCount - 1) or
//this@ChatMessagesList.smoothScrollToPosition(viewAdapter.itemCount - 1)
}
})
这也没有帮助我。首先我将描述我的设置,然后描述预期的行为和当前行为:
我有一个如下所示的 xml:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
<ImageView
android:id="@+id/backgroundImage"
android:layout_width="0dp"
android:layout_height="0dp"
android:contentDescription="@string/image_image_description"
android:scaleType="centerCrop"
android:src="@drawable/chat_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/overlay"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#CCFFFFFF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<app.jooy.messenger.ui.components.generic.chat.chat_header.ChatHeader
android:id="@+id/chat_header"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<app.jooy.messenger.ui.components.generic.chat.chat_message_list.ChatMessagesList
android:id="@+id/chat_messages_list"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/chat_options_chooser"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/chat_header" />
<app.jooy.messenger.ui.components.generic.chat.chat_options_chooser.ChatOptionsChooser
android:id="@+id/chat_options_chooser"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/chat_emoji_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<app.jooy.messenger.ui.components.generic.chat.chat_emoji_bar.ChatEmojiBar
android:id="@+id/chat_emoji_bar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@id/chat_action_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<app.jooy.messenger.ui.components.generic.chat.chat_action_bar.ChatActionBar
android:id="@+id/chat_action_bar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@color/colorActionBarBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</merge>
重要的视图是chat_messages_list RecyclerView,这是我的RecyclerView,其实现如下(为简单起见删除了一些内容):
@ExperimentalCoroutinesApi
@ReactiveComponent
class ChatMessagesList @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ReactiveRecyclerView<ChatMessagesList.ViewState, ChatMessagesList.ViewAction, ChatMessagesList.ViewStructure>(
ViewState(),
context,
attrs,
defStyleAttr
) {
private val viewAdapter = ChatMessagesListAdapter()
init {
setHasFixedSize(true)
layoutManager = object : LinearLayoutManager(context) {
init {
stackFromEnd = true
}
}
viewAdapter.registerAdapterDataObserver(object : AdapterDataObserver() {
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
//(layoutManager as? LinearLayoutManager)?.scrollToPositionWithOffset(0, 0)
//(layoutManager as? LinearLayoutManager)?.smoothScrollToPosition(this@ChatMessagesList, null, viewAdapter.itemCount - 1)
//this@ChatMessagesList.smoothScrollToPosition(0)
}
})
registerTypes(viewAdapter)
adapter = viewAdapter
addItemDecoration(getDecoration())
setPadding(0, 6.toPx(), 0, 6.toPx())
clipToPadding = false
}
}
此外,我可以告诉你,我的适配器肯定会调用正确的 notifyItemRangeInserted, ... 调用。
预期行为:
RecyclerView 应该从屏幕底部的第一个项目开始,并且始终如果添加新项目,则应将其添加到底部并滚动到。最后底部的新项目应该看起来像是从底部推入的。
当前行为:
项目从底部开始堆叠,直到RecyclerView 内的可见空间未满,所有的动画都非常漂亮,但是一旦可见空间已满,项目就会添加到底部但不会滚动到。正如某些人所期望的那样,我想要实现的功能是聊天功能。
补充说明:
如果我将this@ChatMessagesList.smoothScrollToPosition(viewAdapter.itemCount - 1) 添加到onItemRangeInserted 回调中,它会转到底部但没有动画,它只是跳到那里。
【问题讨论】:
标签: android android-recyclerview android-viewholder smooth-scrolling