首页 > 解决方案 > 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 { }



        }

你们有机会知道我如何解决这个问题吗?

标签: listviewxamarin.formsobservablecollection

解决方案


在重新加载发生后添加:

listview_AllChats.ScrollTo(item, ScrollToPosition.Start, false);

解决它!


推荐阅读