droidNDK
droidNDK

Reputation: 85

Horizontal List View Xamarin forms

I am trying to implement Horizontally scrolling List view in Xamarin forms and i have tried several libraries but could not find good solution. Is this possible in Xamrin forms (without renders) and is there working library i can use?

Upvotes: 1

Views: 2511

Answers (3)

Renjith
Renjith

Reputation: 682

Inorder to get a horizontal scrolling listview you have to create a custom scrollView as follow and use this custom control in XAML

public class ImageGallery : ScrollView { readonly StackLayout _imageStack;

    public ImageGallery()
    {
        this.Orientation = ScrollOrientation.Horizontal;

        _imageStack = new StackLayout
        {
            Orientation = StackOrientation.Horizontal
        };

        this.Content = _imageStack;
    }

    public IList<View> Children
    {
        get
        {
            return _imageStack.Children;
        }
    }


    public static readonly BindableProperty ItemsSourceProperty =
        BindableProperty.Create<ImageGallery, IList>(
            view => view.ItemsSource,
            default(IList),
            BindingMode.TwoWay,
            propertyChanging: (bindableObject, oldValue, newValue) => {
                ((ImageGallery)bindableObject).ItemsSourceChanging();
            },
            propertyChanged: (bindableObject, oldValue, newValue) => {
                ((ImageGallery)bindableObject).ItemsSourceChanged(bindableObject, oldValue, newValue);
            }
        );

    public IList ItemsSource
    {
        get
        {
            return (IList)GetValue(ItemsSourceProperty);
        }
        set
        {

            SetValue(ItemsSourceProperty, value);
        }
    }
    void ItemsSourceChanging()
    {
        if (ItemsSource == null)
            return;
    }
    void ItemsSourceChanged(BindableObject bindable, IList oldValue, IList newValue)
    {
        if (ItemsSource == null)
            return;

        var notifyCollection = newValue as INotifyCollectionChanged;
        if (notifyCollection != null)
        {
            notifyCollection.CollectionChanged += (sender, args) => {
                if (args.NewItems != null)
                {
                    foreach (var newItem in args.NewItems)
                    {

                        var view = (View)ItemTemplate.CreateContent();
                        var bindableObject = view as BindableObject;
                        if (bindableObject != null)
                            bindableObject.BindingContext = newItem;
                        _imageStack.Children.Add(view);
                    }
                }
                if (args.OldItems != null)
                {
                    // not supported
                    _imageStack.Children.RemoveAt(args.OldStartingIndex);
                }
            };
        }
    }
    public DataTemplate ItemTemplate
    {
        get;
        set;
    }
    public static readonly BindableProperty SelectedItemProperty =
        BindableProperty.Create<ImageGallery, object>(
            view => view.SelectedItem,
            null,
            BindingMode.TwoWay,
            propertyChanged: (bindable, oldValue, newValue) => {
                ((ImageGallery)bindable).UpdateSelectedIndex();
            }
        );

    public object SelectedItem
    {
        get
        {
            return GetValue(SelectedItemProperty);
        }
        set
        {
            SetValue(SelectedItemProperty, value);
        }
    }

    void UpdateSelectedIndex()
    {
        if (SelectedItem == BindingContext)
            return;

        SelectedIndex = Children
            .Select(c => c.BindingContext)
            .ToList()
            .IndexOf(SelectedItem);

    }

    public static readonly BindableProperty SelectedIndexProperty =
        BindableProperty.Create<ImageGallery, int>(
            carousel => carousel.SelectedIndex,
            0,
            BindingMode.TwoWay,
            propertyChanged: (bindable, oldValue, newValue) => {
                ((ImageGallery)bindable).UpdateSelectedItem();
            }
        );

    public int SelectedIndex
    {
        get
        {
            return (int)GetValue(SelectedIndexProperty);
        }
        set
        {
            SetValue(SelectedIndexProperty, value);
        }
    }

    void UpdateSelectedItem()
    {
        SelectedItem = SelectedIndex > -1 ? Children[SelectedIndex].BindingContext : null;
    }
}`

Now you can use the custom ScrollView in XAML to get a horizontal scrolling list

<custom:ImageGallery ItemsSource="{Binding ImageList}" HeightRequest="100"> <custom:ImageGallery.ItemTemplate> <DataTemplate> <-- layout and related stuffs--> </DataTemplate> </custom:ImageGallery.ItemTemplate> </custom:ImageGallery>

Upvotes: 1

Stephane Delcroix
Stephane Delcroix

Reputation: 16222

Some create Horizontal ListViews by Rotating the ListView, and then Rotating back the elements.

That's a hack, you have to make sure it doesn't mess with your layout (do not put that in a Grid e.g.). But it works fine.

Upvotes: 0

Jay Patel
Jay Patel

Reputation: 628

try https://www.nuget.org/packages/HorizontalListView1.1/

Sample usage:(XAML)

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
x:Class="test.ListPage" xmlns:Controls="clr-namespace:test;assembly=test"> 

<Controls:HorizontalListView ItemsSource="{Binding Categories}" ListOrientation="Horizontal"> 
  <Controls:HorizontalListView.ItemTemplate> 
    <DataTemplate> 
    <Label Text="{Binding Name}" Grid.Row="0" YAlign="Center" /> 
    </DataTemplate> 
  </Controls:HorizontalListView.ItemTemplate> 
  </Controls:myControl>

Upvotes: 0

Related Questions