我使用Recyclerview替换了ListView,但我希望保持Recyclerview始终滚动到底部。
ListView可以使用此方法setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL)
对于RecyclerView, 我使用方法smoothScrollToPosition(myAdapter.getItemCount() - 1)
但当软键盘弹出时,它会替换掉RecyclerView的内容。
我使用Recyclerview替换了ListView,但我希望保持Recyclerview始终滚动到底部。
ListView可以使用此方法setTranscriptMode(AbsListView.TRANSCRIPT_MODE_ALWAYS_SCROLL)
对于RecyclerView, 我使用方法smoothScrollToPosition(myAdapter.getItemCount() - 1)
但当软键盘弹出时,它会替换掉RecyclerView的内容。
RecyclerView
底部,这在聊天应用程序中非常有用,只需在LinearLayoutManager
上调用setStackFromEnd(true)
,就可以使键盘将列表项固定在底部(键盘)而不是顶部。LinearLayoutManager
上调用吗? - Kirill KulakovstackFromEnd
不起作用,而在代码中调用该方法可以。 - gunessrecyclerView.scrollToPosition(getAdapter().getItemCount()-1);
smoothScrollToPosition()
方法即可。
一个更简单的解决方案是为您的活动根视图添加一个已知ID,比如“@+id/activityRoot”,将GlobalLayoutListener钩入ViewTreeObserver,从那里计算您的活动视图根与窗口大小之间的大小差异:
final View activityRootView = findViewById(R.id.activityRoot);
activityRootView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = activityRootView.getRootView().getHeight() - activityRootView.getHeight();
if (heightDiff > 100) {
recyclerView.smoothScrollToPosition(myAdapter.getItemCount() - 1);
}
}
});
简单易懂!
myAdapter.getItemCount() > 0
。否则,当列表中没有项目时启动应用程序时,它将崩溃,因为它尝试滚动到位置-1。 - Someone Somewhere我也遇到了同样的问题。但是以下代码帮助了我。希望这对你有用。
在这里,状态是arraylist。
recyclerView.scrollToPosition(staus.size()-1);
recyclerView.scrollToPosition(showAdapter.getItemCount()-1);
我自己也遇到了这个问题,最终我创建了自己的LayoutManager来解决它。这是一个相当简单的解决方案,可以分为三个步骤:
将stackFromEnd
设置为true。
确定是否应该在每次调用onItemsChanged
时将forceTranscriptScroll
设置为true。根据文档,当适配器的内容发生更改时,会调用onItemsChanged
。如果transcriptMode
设置为Disabled
,则forceTranscriptScroll
始终为false
;如果设置为AlwaysScroll
,则始终为true
;如果设置为Normal
,则仅在适配器中的最后一个项目完全可见时才为true。
在onLayoutCompleted
中,如果forceTranscriptScroll
设置为true
且列表中的最后一个项目尚未完全可见,则滚动到列表中的最后一个项目。
以下是实现这三个步骤的代码:
import android.content.Context
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class TranscriptEnabledLinearLayoutManager(context: Context, transcriptMode: TranscriptMode = TranscriptMode.Normal) :
LinearLayoutManager(context) {
enum class TranscriptMode {
Disabled, Normal, AlwaysScroll
}
private var transcriptMode: TranscriptMode = TranscriptMode.Disabled
set(value) {
field = value
// Step 1
stackFromEnd = field != TranscriptMode.Disabled
}
private var forceTranscriptScroll = false
init {
this.transcriptMode = transcriptMode
}
// Step 2
override fun onItemsChanged(recyclerView: RecyclerView) {
super.onItemsChanged(recyclerView)
forceTranscriptScroll = when (transcriptMode) {
TranscriptMode.Disabled -> false
TranscriptMode.Normal -> {
findLastCompletelyVisibleItemPosition() == itemCount - 1
}
TranscriptMode.AlwaysScroll -> true
}
}
// Step 3
override fun onLayoutCompleted(state: RecyclerView.State?) {
super.onLayoutCompleted(state)
val recyclerViewState = state ?: return
if (!recyclerViewState.isPreLayout && forceTranscriptScroll) {
// gets the position of the last item in the list. returns if list is empty
val lastAdapterItemPosition = recyclerViewState.itemCount.takeIf { it > 0 }
?.minus(1) ?: return
val lastCompletelyVisibleItem = findLastCompletelyVisibleItemPosition()
if (lastCompletelyVisibleItem != lastAdapterItemPosition ||
recyclerViewState.targetScrollPosition != lastAdapterItemPosition) {
scrollToPositionWithOffset(lastAdapterItemPosition, 0)
}
forceTranscriptScroll = false
}
}
}
虽然这个问题有点老了,似乎没有一个正确的答案。我认为你在这里需要做的是监听适配器的变化,然后在每次检测到变化时滚动到底部。
这是一个可行的示例
yourAdapter?.registerAdapterDataObserver(object : AdapterDataObserver() {
override fun onChanged() {
yourRecyclerView?.smoothScrollToPosition(yourAdapter?.itemCount ?: 0)
}
})