Hey Developers, happy new year! Let’s talk about UI components today! I have been playing around with custom controls, custom renders and other tools to try to get to the best solution for Cross Platform Horizontal Lists with Xamarin Forms! I reached a few solutions and Would like to share them with you!

If you are in a hurry and really can’t stick around to read the rest of the post, well,  here is the link for the Sample project in Github, clone it, fork it, try it out and be happy!

Like some other UI components in Xamarin Forms, listviews that scroll horizontally are not right out of the box for us to use. In this post, I decided to bring to you a few ways to  implement this control, let’s list them bellow:

  1. Rotated Xamarin Forms ListView.
  2. Custom Control – Grid + Horizontal ScrollView
  3. Custom Renders – Android.RecyclerView & iOS.UICollectionView

1. Rotated Xamarin Forms ListView

Special thanks for the help with this sample to my fellow member of the monkey nights community and fan of DDD @jbalivo.

On the MainPage.xaml of the sample app this is the first List from the top down. As the  title already says, this one is a ListView Rotated 270° with the ContentView of the ItemTemplate also rotated 90°, all inside a RelativeLayout using it’s constraints to keep everything together.


  • Just like using a Forms ListView.
  • CachingStrategy avaiable to use.


  • The scroll bar is sticked to the top of the listview.
  • I personally do not like dealing with RelativeLayout and it’s constraints.
  • Your ItemTemplate HAS TO BE SQUARE, unfortunately there is this blocker. I tried messing with it but the more you poke it, the more it gets angry.

2. Custom Control – Grid + Horizontal ScrollView

I came across this amazing sample in the Hotel 360 sample app that was built for Microsoft Connect(); 2017. You can find the Hotel 360 code here, I highly recommend you to take a look at that repo and check out what those guys did, it is awesome.

On the MainPage.xaml of our sample app this will be the second ListView from the top down also known as middle. You can also check out the UI control code here, this puppy was completely copied from the Hotel 360 app so it is already wrapped with all sorts of properties for us to use.


  • The scroll bar is on the bottom of the control.
  • You can have whatever shape you want for the ItemTemplate.


  • Unlike normal ListViews this puppy does not have CachingStrategy available, it means that all the items in the list you are binding are loaded in memory at the same time. This can become an issue in your app if you load a lot of items, so be very careful when using this!

3. Custom Renders – Android.RecyclerView & iOS.UICollectionView

As usual, when we ran out of options we can always delegate the task to the target platforms! In this case I used Android native RecyclerView and iOS native UICollectionView components, these are really powerful components for Android and iOS platforms, I recommend you to read the documentation and see what other awesome layouts we can build with them.

On the MainPage.xaml the third ListView counting from the top down is where we call this render, you can also find the . As of the publishing of this post, the renders are only loading the list of monkeys in the screen, I did not yet setup the list update, item select command or other common features that we have in ListViews, I will be adding features during February BUT if you feel like contributing here is the link for the Gitrepo issues list, I will be more than happy and honored to accept your pull requests!


  • Cell Recycling is available on both components.
  • The cell can have the shape that you need/wish.


  • I don’t know if it was just me but I spend a whole weekend to set this puppies up, it is quite a lot of code that you have to write to get it up and running.


Like everything in Tech, there are no silver bullets to solve our problems, here we have three ways of solving the same issue, each of the solutions are a fit based on your app needs. Choose wisely.

throw new CauserException();