listview - xamarin.forms: Observablecollection, Listviews in a Chat: 当新消息添加到顶部时,listview 向上移动,shou
问题描述
我正在以 xamarin 形式进行聊天。我使用一个可观察的集合,通过重新加载适配器向其中添加项目。逻辑工作并加载所有消息,例如,当添加消息时(到列表的顶部,而不是底部!),列表视图始终将该项目显示为第一个。但这意味着,由于重新加载“向后”加载下一个项目,因此列表视图再次向上移动,然后加载下一个项目,依此类推。当然,这意味着一旦启用第一次重新加载,它将下载所有项目并移动聊天的最顶部。那个ofc太可怕了。
通常,您会将项目添加到可观察集合的末尾,然后,即使添加了项目,列表视图也会保持原位。但是当添加到顶部时,这种行为不会发生。或者更确切地说,这就是问题所在:添加到顶部的每个新项目都会让列表视图呈现在顶部,但是由于聊天是向后的,所以总是显示列表的顶部而不是底部。
这是我所做的
private async Task ReloadChatMessages(bool scrollToBeginning)
{
if (IsBusy)
return;
isBusy = true;
//reset List, cause we only want our new messages on here
unsortedMessages = new List<ChatType>();
// keep track of download iterations, skipping the first
if (result.Count != 0)
amountOfDownloads++;
if(amountOfDownloads * Constants.NUMBEROFIADSTOLOADATONCECHAT >= totalNumberOfMessagesAvailable)
{
// end reached
listview_AllChats.ItemAppearing -= Handle_ItemAppearing;
endReached = true;
//load last remaining messages
int amountOfRemainingMSGs = (amountOfDownloads * Constants.NUMBEROFIADSTOLOADATONCECHAT) - totalNumberOfMessagesAvailable;
//final load
unsortedMessages = await Chats.GetAllChats(uniqueChatID, 0, amountOfRemainingMSGs);
}
else // regular reload
{
// download messages in reverse order
unsortedMessages = await Chats.GetAllChats(uniqueChatID,
(totalNumberOfMessagesAvailable - (Constants.NUMBEROFIADSTOLOADATONCECHAT * amountOfDownloads)),
Constants.NUMBEROFIADSTOLOADATONCECHAT);
}
// since we insert on loads after second we need to reverse list first
if (result.Count >= Constants.NUMBEROFIADSTOLOADATONCECHAT)
unsortedMessages.Reverse();
//add to all chats, so we are always up to speed with all messages
allChats.AddRange(unsortedMessages);
// format message to our visible chat type
for (int i = 0; i < unsortedMessages.Count; i++)
{
if (result.Count < Constants.NUMBEROFIADSTOLOADATONCECHAT)
result.Add(FormattedChatMessage(unsortedMessages[i]));
else
{
result.Insert(0, FormattedChatMessage(unsortedMessages[i]));
}
}
//traverse list backwards and add number to messsage
int counter = result.Count;
for(int i = totalNumberOfMessagesAvailable; i > (totalNumberOfMessagesAvailable-result.Count); i--)
{
result[counter-1].numberOfMessage = i;
counter--;
}
isBusy = false;
// add to chatview if not already added
if (listview_AllChats.ItemsSource == null)
listview_AllChats.ItemsSource = result;
if(amountOfDownloads < 2 || scrollToBeginning)
{
if (result.Count == 0)
return;
VisibleChatType target = new VisibleChatType();
try
{
target = result[result.Count];
}
catch
{
target = result[result.Count-1];
}
try
{
listview_AllChats.ScrollTo(target, ScrollToPosition.End, false);
}
catch
{
}
}
}
和重新加载适配器:
private async void Handle_ItemAppearing(object sender, ItemVisibilityEventArgs e)
{
try
{
var item = e.Item as VisibleChatType;
if (isBusy)
return;
//offset important
if (item.numberOfMessage == totalNumberOfMessagesAvailable + 1 - (result.Count))
{
//LoadMore
await ReloadChatMessages(false);
}
}
catch { }
}
你们有机会知道我如何解决这个问题吗?
解决方案
在重新加载发生后添加:
listview_AllChats.ScrollTo(item, ScrollToPosition.Start, false);
解决它!
推荐阅读
- ios - Swift - NSInternalInconsistencyException',原因:'请求第 (1) 节的行数超出范围
- android - Websocket 安全错误:未验证主机名
- angular - 无法启动连接:错误并且无法加载资源:SignalR 中的 net::ERR_SSL_PROTOCOL_ERROR
- python - 如何将相关图保存为png
- flutter - 我在 windows 的 android studio 中设置颤振时出错,我已经更新并拥有最新版本的颤振和 android studio
- docker - 如何使用 docker log 在每次匹配特定字符串后指定日志数?
- node.js - 干净退出 - 重新启动前等待更改?
- vim - 如何在 vim 编辑器中快速按 enter
- paypal - 如何在 PayPal 客人付款上显示“使用借记卡或信用卡付款”按钮而不是“以客人身份结帐”
- android - 如何使用 openweathermap API 获取未来 3 天天气预报的响应