We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

ScrollToRowIndex works on Android but not iOS

I haven't been able to get ScrollToRowIndex to work in iOS. 

My app basically needs to load data from the ViewModel in the OnAppearing() function, and then immediately scroll to the bottom when finished. It is a chat-line app so the newest message is always on the bottom. If someone selects a thread, it forwards to a list of messages and it needs to be immediately scrolled to the bottom.

This works okay in Android but not iOS. I'm am using the latest Weekly NuGet packages as well.
I have this in my ContentPage's code behind:

public MsgPage(Conversation selectedThread)
{
InitializeComponent();

iewModel.LoadMessagesAsync(selectedThread.Phone);
msgList.Loaded += MsgListView_Loaded;
}

private void MsgListView_Loaded(object sender, ListViewLoadedEventArgs e)
{
Device.BeginInvokeOnMainThread(() =>
{
int index = msgList.DataSource.DisplayItems.Count;
msgList.LayoutManager.ScrollToRowIndex(index, true);
});
}


When I put a breakpoint after "index" it is always at zero. Its like the ListView doesn't actually have content in it yet when the _Loaded function fires. It always has the proper index on Android, however.

Am I doing this wrong? Should I be scrolling to the bottom elsewhere?

5 Replies

DB Dinesh Babu Yadav Syncfusion Team July 1, 2019 11:59 AM UTC

Hi Alex, 
 
Thanks for contacting Syncfusion support. 
 
We would like to inform that reported issue is the defect in iOS. We have logged a defect report for the reported issue and the fix will be included in upcoming weekly nuget release which is expected to be rolled out on July 16,2019. We will appreciate your patience until then. 
 
 
Meanwhile, you can now overcome the reported issue by calling ScrollToIndex method in CollectionChanged event like below. We have attached the sample for your reference, please find the sample from below link. 
 
 
 
public partial class MainPage : ContentPage 
{ 
        public MainPage() 
        { 
            InitializeComponent(); 
            ViewModel.contactsinfo.CollectionChanged += Contactsinfo_CollectionChanged; 
        } 
 
        private void Contactsinfo_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
        { 
            Device.BeginInvokeOnMainThread(async () => 
            { 
                int index = listView.DataSource.DisplayItems.Count; 
                listView.LayoutManager.ScrollToRowIndex(index, true); 
            }); 
        } 
        protected override void OnAppearing() 
        { 
            ViewModel.GenerateInfo(); 
            listView.ItemsSource = ViewModel.contactsinfo; 
            base.OnAppearing(); 
        } 
} 
 
Please let us know if you have any further queries. 
 
Regards, 
Dinesh Babu Yadav 
 



AL Alex July 1, 2019 06:24 PM UTC

Thanks Dinesh.

A couple other things:
  • I've noticed is that the disableAnimation = true in msgList.LayoutManager.ScrollToRowIndex(index, true) does not seem to do anything in this example. When the page loads, the list is populated and it shows the top of the listbox, then animates scrolling down to the bottom of the list in a kind of stutter-y manner. How can I show the list already scrolled to the bottom instead of showing going through the scrolling motions every time?

  • In your example you have the ViewModel generating the data before base.OnAppearing(). Is this normal? When should I be doing work before OnAppearing() versus after?

  • In your workaround, every time the collection is changed, it will always scroll to the bottom. In my app, this list subscribes to events that occur at random. For example, a delivery or read-receipt may be sent via Firebase or SignalR to the list. In that event, item #10 out of 30 might be changed to show "Message Read". If this happens, the "CollectionChanged" event is triggered and it scrolls the user back to the bottom. What I would actually want is for the list to only scroll to the bottom in the event the whole collection is replaced/reset, or when a new item is added. Not when other aesthetic changes occur.


MM Mageshyadav M Syncfusion Team July 2, 2019 03:31 PM UTC

Hi Alex,  
 
Please find the response for your queries. 
 
Query 
Response 
I've noticed is that the disableAnimation = true in msgList.LayoutManager.ScrollToRowIndex(index, true) does not seem to do anything in this example. When the page loads, the list is populated and it shows the top of the listbox, then animates scrolling down to the bottom of the list in a kind of stutter-y manner. How can I show the list already scrolled to the bottom instead of showing going through the scrolling motions every time? 
If you use AutoFitMode="Height", then scrolling animation will be disabled in Android and IOS platform. Please find the limitations of scrolling with animation, 
 
 
If your query is different from expecting scrolling with animation apart from this limitations, then we can assist you further with suggestions. 
In your example you have the ViewModel generating the data before base.OnAppearing(). Is this normal? When should I be doing work before OnAppearing() versus after? 
Based on your queries, the workaround suggested may not fit your requirement. Hence we suggest you to wait for the fix which we have promised to deliver on July 16, 2019 and fix changes once delivered will work properly with your initial try of populating items in OnAppearing and perform scrolling in loaded event. 
In your workaround, every time the collection is changed, it will always scroll to the bottom. In my app, this list subscribes to events that occur at random. For example, a delivery or read-receipt may be sent via Firebase or SignalR to the list. In that event, item #10 out of 30 might be changed to show "Message Read". If this happens, the "CollectionChanged" event is triggered and it scrolls the user back to the bottom. What I would actually want is for the list to only scroll to the bottom in the event the whole collection is replaced/reset, or when a new item is added. Not when other aesthetic changes occur. 
 
 
Regards,  
Yuvaraj Chandrasekaran 



DB Dinesh Babu Yadav Syncfusion Team July 17, 2019 12:56 PM UTC

Hi Alex, 
 
We are validating the alternative solution for reported requirement with high priority and will let you know the further details by tomorrow. 
 
Regards, 
Dinesh Babu Yadav 



DB Dinesh Babu Yadav Syncfusion Team July 18, 2019 12:12 PM UTC

Hi Alex, 
 
Thanks for the patience. 
 
The DisplayItems count is not updated when ItemsSource is set in the OnAppearing override method since ListView’s LoadedEvent is called on the initial child measure itself where ItemsSource is not set until page OnAppearing invoked. Hence we suggest you to achieve the requirement by calling the ScrollToRowIndex method in OnAppearing method itself like below after setting the ItemsSource. 
 
public partial class MainPage : ContentPage 
{ 
        public MainPage() 
        { 
            InitializeComponent(); 
        } 
 
        protected override void OnAppearing() 
        { 
            ViewModel.GenerateInfo(); 
            listView.ItemsSource = ViewModel.contactsinfo; 
            Device.BeginInvokeOnMainThread(async() => 
            { 
                int index = listView.DataSource.DisplayItems.Count; 
                listView.LayoutManager.ScrollToRowIndex(index, true); 
            }); 
            base.OnAppearing(); 
        } 
} 
 
Please let us know if you require further assistance. 
 
Regards, 
Dinesh Babu Yadav 


Loader.
Up arrow icon