How to get scroll current position upon CollectionChange event in Xamarin?

Issue

I’ve a Xamarin chat app, when i receive new messages it scrolls to the recent received message. I want that to happen if i’m seeing the must recent messages, otherwise if User scrolls to older messages and a new message arrives, i want to be shown a button (like in team) saying “new” and if you click you scroll to the recent message.

The Problem here is that in order to do that i must be able to now what messages user is seeing in the screen, at least know the bottom screen message or just get scroll current position! After knowing that i can do the rest by myself.

This is my OnAppearing method:

    protected override void OnAppearing()
    {
        base.OnAppearing();

        if (viewModel.Messages.Count  0)
        {
            viewModel.LoadItemsCommand.Execute(null);
        }

        viewModel.Messages.CollectionChanged + (sender, e) >
        {
            //GET SCROLL CURRENT POSITION HERE!
            var target  viewModel.Messages[viewModel.Messages.Count - 1];

            ItemsListView.ScrollTo(target, ScrollToPosition.End, false);
        };            
    }

Thank you all!

Solution

Finally i find the way of getting the scroll current position!!

Basically if you have a ListView like me once it already contains a scroll by default you can just do like this:

        YourListViewName.Scrolled + (sender, e) >
        {
            var scrollCurrentVerticalPosition  e.ScrollY;                
        };

For my case instead of making the call inside CollectionChanged event I had to do this:

Create a private variable:

private bool scrollPositionEnd  true;

And inside OnAppearing method:

protected override void OnAppearing()
{
    base.OnAppearing();

    if (viewModel.Messages.Count  0)
    {
        viewModel.LoadItemsCommand.Execute(null);
    }

    viewModel.Messages.CollectionChanged + (sender, e) >
    {            
        if (scrollPositionEnd  true)
        {
            ScrollToEnd();
        }
        else if (GetLastMessage().UserId ! UserId) //so it wont trigger on your own messages
        {
            NewMessagesButton.IsVisible  true;
        }
    };    

    ItemsListView.Scrolled + (sender, e) >
    {
        if (e.ScrollY  0) //when scroll is in bottom ScrollY value is 0 
        {
            scrollPositionEnd  true;

            //if you manually scroll down until the new message
            NewMessagesButton.IsVisible  false;
        }
        else
        {
             scrollPositionEnd  false;
        }
    };
 }

Auxiliary methods:

    //If you click the button event
    private void ButtonScrollClick(object sender, EventArgs e)
    {
        ScrollToEnd();
    }

    private void ScrollToEnd()
    {
        NewMessagesButtonFrame.IsVisible  false;
        Message target  GetLastMessage();
        ItemsListView.ScrollTo(target, ScrollToPosition.End, false);
    }

    private Message GetLastMessage()
    {
        return viewModel.Messages[viewModel.Messages.Count - 1];
    }

Thank you guys for you tips and if you enjoy my answer fill free to vote it up 🙂

Answered By – MarchalPT

Leave a Comment