This is a migrated thread and some comments may be shown as answers.

ScrollToItem /Bottom

9 Answers 353 Views
ListView - Xamarin.iOS
This is a migrated thread and some comments may be shown as answers.
Julian
Top achievements
Rank 1
Julian asked on 21 Mar 2017, 03:36 PM

Hey guys,

I am currently implementing a custom renderer for my xamarin.forms ios application. I want to scroll to the bottom of the Listview but currently I don't see a way to do this.

I tryed to use the "ScrollToItem" method, but to use this method i need the indexpath of the last cell in my Listview and I don't know how to get this.

could you help me to solve this problem?

 

Best regards

Julian

9 Answers, 1 is accepted

Sort by
0
Lance | Manager Technical Support
Telerik team
answered on 21 Mar 2017, 05:49 PM
Hello Julian,

You can get an array of the indexPaths for items in the RadListView's visible items using this property (or this one if you want the indexPath of the selected items).

Ultimately, to get the indexPath for any cell, you can use getIndexPathForCell.

Once you get the indexPath on the last cell in your RadListView, then you can call scrollToItemAtIndexPath.

Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Julian
Top achievements
Rank 1
answered on 22 Mar 2017, 05:08 PM

Hey Lance and thanks for your fast reply.

In my case IndexPathsForVisibleItems doesn't contain any items.

My code looks like this, am I doing anything wrong?

Best regards

Julian

public class MyListViewRenderer : Telerik.XamarinForms.DataControlsRenderer.iOS.ListViewRenderer
    {
        public ChatList View = new ChatList();
 
        protected override void OnElementChanged(Xamarin.Forms.Platform.iOS.ElementChangedEventArgs<Telerik.XamarinForms.DataControls.RadListView> e)
        {
            base.OnElementChanged(e);
 
            if (e.NewElement != null) {
                View = e.NewElement as ChatList;
               View.Scroll += MyListViewRenderer_Scroll;
            }
 
        }
 
 
        public override bool AccessibilityScroll(UIAccessibilityScrollDirection direction)
        {
            return base.AccessibilityScroll(direction);
 
        }
        private void MyListViewRenderer_Scroll(object sender, EventArgs e)
        {
            if (Control.IndexPathsForVisibleItems.Count() > 0)
            {
                var a = Control.IndexPathsForVisibleItems.LastOrDefault();
                Control.ScrollToItem(a, UICollectionViewScrollPosition.Bottom, false);
            }
        }
    }
0
Lance | Manager Technical Support
Telerik team
answered on 22 Mar 2017, 08:22 PM
Hello Julian,

With what you've provided for code, it looks functional. I would put a breakpoint or Debug.WriteLine, inside the if statement to ensure that the a variable has a valid value.

However, there is a problem with your approach of using the visible items. You'll never be able to get the last item in the unless the user happens to already be at the bottom.

Instead, you could just create the indexPath manually, like this (I use 49 so that it scrolls to the 50th item, but you can pass it the total number of items, minus 1):

var ip = NSIndexPath.Create(0,49);
                 
Control.ScrollToItem(ip, UICollectionViewScrollPosition.Top, true);

To help, I've attached a demo that is based off your code.

Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Julian
Top achievements
Rank 1
answered on 29 Mar 2017, 07:35 PM

Hey Lance, 

thank you for your example! 

In my app the Listview is scrolling but not to the End. May it be connected to the fact that i have a dynamic rowheight?

 

Best regards

Julian

0
Lance | Manager Technical Support
Telerik team
answered on 03 Apr 2017, 03:19 PM
Hello Julian,

I can't tell what's wrong with your specific implementation without a reproducible to debug directly.

You can try a slightly different approach that also take into account the number of groups and number of items in each group.

Here's the full implementation:

1 - Define the renderer's interface in the portable project:

public interface ICustomListViewRenderer
{
    void ScrollTo(int index, int section);
 
    int NumberOfGroups();
 
    int NumberOfItemsInGroup(int group);
}


2 - Define the custom RadListView in the portable project:

public class CustomRadListView : RadListView
{
    public ICustomListViewRenderer Renderer { get; set; }
 
    public void ScrollTo(int index, int group)
    {
        Renderer?.ScrollTo(index, group);
    }
 
    public int NumberOfGroups()
    {
        return Renderer?.NumberOfGroups() ?? 0;
    }
 
    public int NumberOfItemsInGroup(int group)
    {
        return Renderer?.NumberOfItemsInGroup(group) ?? 0;
    }
}


3 - In the iOS project, implement the interface:

public class CustomListViewRenderer : ListViewRenderer, ICustomListViewRenderer
    {
        public int NumberOfGroups()
        {
            return (int)(this.Control?.NumberOfSections ?? 0);
        }
 
        public int NumberOfItemsInGroup(int group)
        {
            return (int)(this.Control?.NumberOfItemsInSection(group) ?? 0);
        }
 
        public void ScrollTo(int index, int group)
        {
            if (group < NumberOfGroups() && index < NumberOfItemsInGroup(group))
            {
                var indexPath = NSIndexPath.FromItemSection(index, group);
                this.Control.ScrollToItem(indexPath, UICollectionViewScrollPosition.Top, true);
            }
        }
 
        protected override void OnElementChanged(Xamarin.Forms.Platform.iOS.ElementChangedEventArgs<Telerik.XamarinForms.DataControls.RadListView> e)
        {
            base.OnElementChanged(e);
 
            var oldElement = e.OldElement as CustomRadListView;
            if (oldElement != null)
            {
                oldElement.Renderer = null;
            }
 
            var newElement = e.NewElement as CustomRadListView;
            if (newElement != null)
            {
                newElement.Renderer = this;
            }
        }
    }



Here's an example of using it in a Xamarin Forms's view

public MainPage()
{
    var lv = new CustomRadListView { ItemsSource = Enumerable.Range(0, 1000) };
    var btn = new Button { Text = "scroll" };
 
    btn.Clicked += (sender, e) =>
    {
        lv.ScrollTo(50, 0);
    };
 
    var grid = new Grid
    {
        RowDefinitions = new RowDefinitionCollection {
                    new RowDefinition { Height = GridLength.Star },
                    new RowDefinition { Height = GridLength.Auto }
        }
    };
 
    grid.Children.Add(lv, 0, 0);
    grid.Children.Add(btn, 0, 1);
 
    this.Content = grid;
}


Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Julian
Top achievements
Rank 1
answered on 11 Apr 2017, 11:42 AM

Hey Lance, 

I uploaded an example Project where you can see how I use the ListView.

https://www.file-upload.net/download-12432750/TestProj.zip.html

There you can reproduce my scrollproblem.

 

Best regards

Julian

0
Lance | Manager Technical Support
Telerik team
answered on 12 Apr 2017, 01:44 PM
Hello Julian,

Thank you for preparing a repro project. Unfortunately, that site you used to upload it to is laden with malicious attacks and I cannot safely download it.

I have prepared this folder for you to upload the project to (for security reasons, I've set the expiration of that link for a couple days because this is a public forum).

Once you've uploaded it, come back here and let me know. I'll then take a look and see what I can do to improve the RadlistView experience.

Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Julian
Top achievements
Rank 1
answered on 13 Apr 2017, 08:02 AM

I uploaded my Testproject to your folder. 
To get it run you need to add the Telerik .dll since I removed it for posting the project.

Thanks alot for your support Lance!

Julian

0
Lance | Manager Technical Support
Telerik team
answered on 13 Apr 2017, 07:49 PM
Hi Julian,

Thank you for sharing the project, however it is not buildable. You have several problems with your project references (other than removing the Telerik one). For, example one of the references has a hard path to the Packages folder instead of letting Nuget handle the project references.

Looking at the code, I have a couple comments

It looks like you did not apply the approach I showed in my last reply that takes into account groups, this part of the renderer determines the indexPath using both the item index as well as the group

var indexPath = NSIndexPath.FromItemSection(index, group);


You have a little more control over the placement of the item when it's scrolled. See the Control.ScrollToItem() method in the renderer

this.Control.ScrollToItem(indexPath, UICollectionViewScrollPosition.Top, true);


Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
ListView - Xamarin.iOS
Asked by
Julian
Top achievements
Rank 1
Answers by
Lance | Manager Technical Support
Telerik team
Julian
Top achievements
Rank 1
Share this question
or