Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
executable file 114 lines (92 sloc) 4.02 KB
id title date author layout guid permalink dsq_thread_id categories
2031
A little and simple Bindable (Horizontal) Scroll View
2016-01-10 17:01:13 +0000
fabiocozzolino
post
/a-little-and-simple-bindable-horizontal-scroll-view/
5274923814
Xamarin

In one project I was working on, a page needs to show a short horizontal and scrollable list of items (something like the Apple App Store app). Xamarin.Forms offers the ability to use a ScrollView control to show a list of items horizontally but, in my case, the items I must to show comes from a dinamically populated list. In that case I’ve extended the ScrollView control and added the ItemsSource and ItemTemplate property.

public class TLScrollView : ScrollView
{
	public static readonly BindableProperty ItemsSourceProperty =
		BindableProperty.Create("ItemsSource", typeof(IEnumerable), typeof(TLScrollView), default(IEnumerable));

	public IEnumerable ItemsSource
	{
		get { return (IEnumerable)GetValue(ItemsSourceProperty); }
		set { SetValue(ItemsSourceProperty, value); }
	}

	public static readonly BindableProperty ItemTemplateProperty =
		BindableProperty.Create("ItemTemplate", typeof(DataTemplate), typeof(TLScrollView), default(DataTemplate));

	public DataTemplate ItemTemplate
	{
		get { return (DataTemplate)GetValue(ItemTemplateProperty); }
		set { SetValue(ItemTemplateProperty, value); }
	}
}

After that, I’ve added a simple method, Render, to populate the ScrollView:

public void Render ()
{
	if (this.ItemTemplate == null || this.ItemsSource == null)
		return;
	
	var layout = new StackLayout ();
	layout.Orientation = this.Orientation == ScrollOrientation.Vertical 
		? StackOrientation.Vertical : StackOrientation.Horizontal;

	foreach (var item in this.ItemsSource) {
		var viewCell = this.ItemTemplate.CreateContent () as ViewCell;
		viewCell.View.BindingContext = item;
		layout.Children.Add (viewCell.View);
	}

	this.Content = layout;
}

That method will be called from the TLScrollViewRenderer (iOS and Android are pretty similar). The renderer is a special class that adapts the Xamarin.Forms control into a native control:

[assembly: ExportRenderer(typeof(TLScrollView), typeof(TLScrollViewRenderer))]

namespace TitiusLabs.Forms.iOS.Controls
{
	public class TLScrollViewRenderer : ScrollViewRenderer
	{
		protected override void OnElementChanged(VisualElementChangedEventArgs e)
		{
			base.OnElementChanged(e);

			var element = e.NewElement as TLScrollView;
			element?.Render();
		}
	}
}

Now you can use the TLScrollView in your xaml and create your custom template in this way:

<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:controls="clr-namespace:TitiusLabs.Forms.Controls;assembly=TitiusLabs.Forms" xmlns:local="clr-namespace:FormSamples" x:Class="FormSamples.Core.Views.FormSamplesPage">
	<StackLayout Padding="20">
		<controls:TLScrollView Orientation="Horizontal" ItemsSource="{Binding Items}" HeightRequest="100">
			<controls:TLScrollView.ItemTemplate>
				<DataTemplate>
					<ViewCell>
						<StackLayout Padding="5">
							<controls:TLImageCircle Source="{Binding Image}" HeightRequest="80" WidthRequest="80" />
						</StackLayout>
					</ViewCell>
				</DataTemplate>
			</controls:TLScrollView.ItemTemplate>
		</controls:TLScrollView>
	</StackLayout>
</ContentPage>

This is the final result:

Amazing!

**UPDATE 12.04.2016: some small refactoring to the custom horizontal ScrollView control

**

Full code is available here


You can’t perform that action at this time.