Xamarin.Forms Layout Challenges – Timeline
A layout I’m seeing more and more these days is a timeline of activities. This is useful for things like transportation schedules or class times. So let’s put together a simple layout for a timeline using a ListView with headers and footers and a custom ViewCell.
Page Structure
This page is just a simple ListView, nothing really more complex than that. I turned the Separators off. Set the RowHeight to something that feels nice.
<ListView
x:Name="timelineListView"
ItemTapped="timelineListView_ItemTapped"
ItemsSource="{Binding .}"
RowHeight="75"
SeparatorVisibility="None">
Also, you may notice I have an ItemTapped hooked up that doesn’t do much:
private void timelineListView_ItemTapped(object sender, ItemTappedEventArgs e)
{
timelineListView.SelectedItem = null;
}
It just disables a row from being selected, mainly because it looks rubbish when one of the rows is selected… but of course depending on your layout, you might actually want to do Master / Detail style navigation.
Header
If you want something to appear above your ListView and have it scroll with the ListView use a header.
Pro Tip: Whatever you do, do NOT put a ScrollView around the entire page. Having nested scrolling containers (eg. ScrollView with ListView inside) is just going end with tears. Use a Header instead.
For our header, it’s just a simple stack layout with some labels and a bit of padding
<ListView.Header>
<StackLayout Padding="20,40,0,30">
<Label Style="{StaticResource PageHeaderLabel}" Text="Class Schedule" />
<Label Style="{StaticResource SubHeaderLabel}" Text="8 Mar 2017" />
</StackLayout>
</ListView.Header>
Footer
Down the bottom of the list, we have just put an image. Not for any particularly good reason, just to jazz up the page a bit and show how footers work. You could easily get rid of it and have a nice layout, I figured I’d just include it to complete the header / footer idea.
In our case the footer contains a Grid with two rows. The actual background image “Footer.png” occupies both the rows. Then we have a transparent-to-white gradient image that is overlaid in the first row. Basically just creating a fade in effect for the image.
<ListView.Footer>
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="64" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Image Grid.RowSpan="2" Aspect="AspectFill" HorizontalOptions="Fill" VerticalOptions="Start" Source="YogaImage.png" />
<Image Aspect="Fill" Grid.RowSpan="2" HorizontalOptions="Fill" Source="FadeToWhite.png" />
</Grid>
</ListView.Footer>
ViewCell
All the real magic happens in the ViewCell which defines what each row is going to look like.
At it’s core it’s just a simple Grid with 3 columns and two rows.

The only really interesting bit of this is the actual lines and circles that form the timeline. This is achieved by a thin vertical BoxView that runs the height of the Viewcell. Overlayed in the first row is our circle image. Nothing magical here.
Now you might notice that it uses a ValueConverter for the IsVisible property, this is kind of a hack to make the line not appear in the last row. Our model object (which would actually probably be a ViewModel in a real app) has a property called IsLast which is set to true for the last row. And then we have a NotBooleanConverter assigned to the IsVisible of the line, so basically the line isn’t rendered on the last row. It feels a bit awkward, but off the top of my head, given the time, I couldn’t think of a better option.
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid ColumnSpacing="0" RowSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="30" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label HorizontalOptions="Center" Style="{StaticResource ClassTimeLabel}" Text="{Binding ClassTime, StringFormat='{0:H:mm}'}" />
<Label
Grid.Column="2"
Margin="20,0"
Style="{StaticResource ClassNameLabel}"
Text="{Binding ClassName}" />
<Label
Grid.Row="1"
Grid.Column="2"
Margin="20,0"
Style="{StaticResource ClassInstructorLabel}"
Text="{Binding Instructor}" />
<BoxView
Grid.RowSpan="2"
Grid.Column="1"
BackgroundColor="{StaticResource TimelineColor}"
HorizontalOptions="Center"
IsVisible="{Binding IsLast, Converter={local:NotBooleanConverter}}"
VerticalOptions="Fill"
WidthRequest="3" />
<Image Grid.Column="1" Source="Bullet.png" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
Wrap Up
So that is it, a simple timeline using a ListView. It works pretty nicely.
Here are some links for further information about some of the techniques:
As YouTubers would say: “let me know in the comments if you liked this” 🙂 Also, If you have any layouts that you thing would be interesting to cover, just let me know.
Oh yeah, and you can grab the project over at https://github.com/kphillpotts/XamarinFormsLayoutChallenges
Also, make sure you check out some of the other layouts in Xamarin.Forms Layout Challenges.
Happy Layouts!