ListView 更新后滚动到顶部
Posted
技术标签:
【中文标题】ListView 更新后滚动到顶部【英文标题】:ListView scrolls to top after updating it 【发布时间】:2018-02-24 16:35:32 【问题描述】:我有一个 mChildEventListener
查询来自 Firebase Database
的前 n 个项目和另一个 mChildEventListener2
(当用户向上滚动并单击 Load More
按钮时触发)查询对于接下来的 n 项,并将它们添加到 ChatMessagesList
。
当用户单击Load More
按钮时:ChatMessagesList
被更新,notifyDataSetChanged
被调用。 mMessageListView
已更新,但每次都会向下滚动到底部。由于 xml 属性,我解释了这种行为:android:transcriptMode="alwaysScroll"
。
当我删除transcriptMode="alwaysScroll"
并且用户按下Load More
按钮时,mMessageListView
这次滚动到顶部。
这些行为都不是我们想要的。我希望当用户按下按钮时,mMessageListView
将保持其滚动位置。 (原因很明显)
我尝试从新线程调用notifyDataSetChanged
。没有结果。
我尝试使用listView.setSelectionFromTop(lastViewedPosition, topOffset);
或list.smoothScrollToPosition();
,但都没有达到我想要的流畅体验。
mMessageListView
更新后如何保持滚动位置?
这是代码:
private ChildEventListener mChildEventListener;
private ChildEventListener mChildEventListener2;
List<ChatMessage> ChatMessages = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState)
...
mMessageAdapter = new MessageAdapter(this, R.layout.item_message_sent, ChatMessages);
mMessageListView.setAdapter(mMessageAdapter);
mChildEventListener = new ChildEventListener()
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s)
if(i == 0)
current_last_key = dataSnapshot.getKey();
else
ChatMessage chatMessage = dataSnapshot.getValue(ChatMessage.class);
mMessageAdapter.add(chatMessage);
i++;
...
;
Query messagesQuery = mDatabaseReference.child("chat_messages").
child(chatId).limitToLast(25);
messagesQuery.addChildEventListener(mChildEventListener);
...
@Override
public void onClick(View v)
j = 0;
mChildEventListener2 = new ChildEventListener()
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s)
if(!dataSnapshot.getKey().equals(current_last_key))
if (j == 0)
current_last_key = dataSnapshot.getKey();
else
ChatMessage chatMessage = dataSnapshot.getValue(ChatMessage.class);
ChatMessages.add(j- 1, chatMessage);
else
ChatMessage chatMessage = dataSnapshot.getValue(ChatMessage.class);
ChatMessages.add(0 , chatMessage);
loadMoreTextView.setVisibility(View.GONE);
mMessageAdapter.notifyDataSetChanged();
j++;
... ;
Query query = mDatabaseReference.child("chat_messages").
child(chatId).orderByKey().endAt(current_last_key).limitToLast(10);
query.addChildEventListener(mChildEventListener2);
【问题讨论】:
【参考方案1】:notifyDataSetChanged()
通知附加的观察者底层数据已更改,任何反映数据集的视图都应自行刷新。
尝试更新时是否再次调用“onCreate()”
【讨论】:
我没有看到相关性。请详细说明【参考方案2】:FirebaseUI lib 为您处理所有这些并简化您的代码。
顺便说一句,您可以使用 mAdapter.notifyItemInserted(ChatMessages.size() - 1);
或 mMessageAdapter.notifyItemRangeInserted(ChatMessages.size() - 1, ChatMessages.size() - 1 + numberOfItemsBeingInserted);
并进行其他必要的更改以使其正常工作,而不是使用 mMessageAdapter.notifyDataSetChanged();
【讨论】:
你的意思是 FirebaseUI 库处理数据分页? 是的!只需使用FirebaseIndexRecyclerAdapter(Class<T> modelClass, @LayoutRes int modelLayout, Class<VH> viewHolderClass, Query keyQuery, DatabaseReference dataRef)
构造函数而不是FirebaseRecyclerAdapter<Food, FoodCardViewHolder>( Food.class, R.layout.card_view_food, FoodCardViewHolder.class, foodInfoRef)
不过,使用 FirebaseIndexRecyclerAdapter
需要我索引我的 ChatMessages
,这是我避免的事情。我已经对我的数据进行了分页,我只是遇到了ListView
的问题以上是关于ListView 更新后滚动到顶部的主要内容,如果未能解决你的问题,请参考以下文章
Flutter ListView.builder在滚动时结结巴巴并跳到顶部[重复]