Xamarin.Forms Horizontal Listview Explained

il

The greatest advantage of using Xamarin Forms is obviously the Binding system and the viewmodels. Especially, collections of data fits perfectly with ListViews allowing views prototyping and decoupling of views and models.

Quite often you need to show List of elements in a row, perhaps with a scrolling pane. For instance, you are trying to show an horizontal list of images or buttons which are not predetermined, but changes on user inputs or remote response.

If you are getting started with Xamarin.Forms documentation really not provide any info about Horizontal ListViews and you think they can’t be done, so you start browsing the Forum and Stackoverflow, which quite often redirect you to download a component, to write Platform specific code. Things mess up quite soon.

Fortunately, your search is over. You can make Horizontal ListViews with Bindings without doing much more than write few Xaml rows of code. Let’s go understand the logic.

Horizontal ListViews in Xaml basics

First, you have to know that each element in Xaml derive from base class that has Rotation property.

  • Rotation property is used to get and set the current Rotation of the element.

First step to create an Horizontal ListView is Rotate 270 degrees (for left to right) or 90 degrees (for right to left) and the inner View element should compensate this rotation as follows:

<ListView Rotatation="270" ItemSource="{Binding Items}">
 <ListView.ItemTemplate>
  <DataTemplate>
   <ViewCell>
    <ContentView Rotatation="90">
     <Image Source="{Binding Source}"></Image>
    </ContentView>
   </ViewCell>
  </DataTemplate>
 </ListView.ItemTemplate>
</ListView>

If you try this code you can see that dimensions are all messed up. The problem here is that listview sizes are calculated before rotation. If your list view is wider than taller you’ll probably see it floating vertically on other elements of the page. This is not the required behavior.

Let’s see how to fix layout.

Fixing Horizontal ListView Layout

The trick here is all about wrapping the ListView in a container and constraint the ListView to match conteiner bounds.

The element in Xamarin.Forms to do this is the Relative Layout.

First, we wrap the ListView in a RelativeLayout element and set the Layout Height to the desired height:

<RelativeLayout HeightRequest="60">
 <ListView Rotatation="270" ItemSource="{Binding Items}" RowHeight="60">
   ....
 </ListView>
</RelativeLayout>

In this example we will show square images, so we’ll also set RowHeight in ListView equal to RelativeLayout Height. Note that as the ListView is rotated the ListView.RowHeight property describe how wide the element is, while RelativeLayout.HeightRequest property describe how tall the element is. Just not get confused with rotation and names.

Second, we need to tell the ListView to bind to RelativeLayout bounds. This is possible setting the RelativeLayout constraints in the child element.

<RelativeLayout HeightRequest="60">
 <ListView Rotatation="270" ItemSource="{Binding Items}" RowHeight="60"
 RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5, Constant=-30}"
 RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=-0.5, Constant=30}"
 RelativeLayout.WidthConstraint="{ConstraintExpression Type=Constant, Constant=60}"
 RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}">
   ....
 </ListView>
</RelativeLayout>

With XConstraint and YConstraint we adjust ListView X,Y anchors, then we set its Width (don’t forget it’s rotated so it correspond to how tall is shown) to a constant equal to parent height and we set its Height (again its shown width) to its parent width.

If you run this code now you should see the ListView much better. But probably you won’t see any element as they are now shifted out of the visible pane.

Last, indeed, we need to translate the content view on the X axis and make sure that images will fit the available viewport. Hereafter the whole code:

<RelativeLayout HeightRequest="60">
 <ListView Rotatation="270" ItemSource="{Binding Items}" RowHeight="60" SeparatorVisibility="None"
 RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5, Constant=-30}"
 RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=-0.5, Constant=30}"
 RelativeLayout.WidthConstraint="{ConstraintExpression Type=Constant, Constant=60}"
 RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=1}">
  <ListView.ItemTemplate>
   <DataTemplate>
    <ViewCell>
     <ContentView Rotatation="90" Padding="1" TranslationX="60">
      <Image Source="{Binding Source}" HeightRequest="58" WidthRequest="58" Aspect="AspectFill"></Image>
     </ContentView>
    </ViewCell>
   </DataTemplate>
  </ListView.ItemTemplate>
 </ListView>
</RelativeLayout>

Here you are! Your Horizontal ListView for Xamarin.Forms in XAML is ready

You can now play with Rotation, Width and Height to obtained the desired effect. Just don’t forget that ListView Width and Height refers to element Width and Height and do not take in consideration that you have Rotate the element.

If you have downloaded strange components get rid of them, notwithstanding if you have written a fantastic code and you want to share just put a comment below. We are keen to know about other solutions for the Best Horizontal ListView in Xamarin.Forms.

Annunci

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...