It is well known that good user interfaces should not be crowded with a lot of information. A page in a mobile app should not have too many visual elements displayed at the same time. If it does, they should at least be displayed in an appropriate way, or at the user’s will.
Today we will create a control. which gives your users the power to hide or display components of your user interface at will (an Accordion in Xamarin Forms). We will use a few components of Xamarin Forms, and no platform specific code. These components include: The ContentView, Animations, Bindable Propoerties.
You can get the source code for the demo application here.
Building The Accordion in Xamarin Forms
Before we start implementing, let’s have an overview of the components of the Accordion View we will build.
- 1- The Title which will give an overview of the view’s content
- 2- The Indicator, which will move depending on wether the accordion is open or closed.
- 3- The Content, which will contain the visual elements to be displayed by the accordion. This component will also be animated.
To build our accordion in Xamarin Forms, we will use a content view. We will customize this content view and give it the properties and animations we need to.
If you like this post, you can chose to follow me on Twitter or Github and subscribe to this page’s notifications to stay updated with new articles or like my page on Facebook.
Implementation
The Title
This is the easiest part of it all. The title will be a label we will place in the visual hierachy of our custom control. Our accordion is then added a bindable property “Title”. This title property is bound to the label’s text property.
1 2 3 4 5 6 7 | public static readonly BindableProperty TitleBindableProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(Accordion), default(string)); public string Title { get => (string)GetValue(TitleBindableProperty); set => SetValue(TitleBindableProperty, value); } |
The Indicator
This component is a content view of its own. It is made to be a content view so that its content can be modified outside of our accordion.
1 2 3 4 | <ContentView x:Name="_indicatorContainer" Content="{Binding Source={x:Reference _accordion_view_123}, Path=IndicatorView}" HorizontalOptions="End" Grid.Column="1" VerticalOptions="Center"/> |
To make it easy to set the content of our indicator, we add a bindable property of type “View” known as “IndicatorView”.
1 2 3 4 5 6 7 | public static readonly BindableProperty IndicatorViewProperty = BindableProperty.Create(nameof(IndicatorView), typeof(View), typeof(Accordion), default(View)); public View IndicatorView { get => (View)GetValue(IndicatorViewProperty); set => SetValue(IndicatorViewProperty, value); } |
Since we need to open and close our indicator, there should be a property to command these actions. This bindable property is the “IsOpen” property. When this property is changed, Animations and VisualStates are changed depending on its value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | private static void IsOpenChanged(BindableObject bindable, object oldValue, object newValue) { bool isOpen; if (bindable != null && newValue != null) { var control = (Accordion)bindable; isOpen = (bool)newValue; if (control.IsOpen == false) { VisualStateManager.GoToState(control, "Open"); control.Close(); } else { VisualStateManager.GoToState(control, "Closed"); control.Open(); } } } |
The Content
Now let’s make it possible to set the content outside of our accordion. To accomplish this, we use the same approach as that of the indicator. We use a content view and create a bindable propoperty. This property is of type View and will make it easy to change our content outside our accordion.
1 2 3 | <ContentView Grid.Row="1" Margin="5" x:Name="_accContent" Content="{Binding Source={x:Reference _accordion_view_123}, Path=AccordionContentView}"/> |
Animation
We have to make this control more interactive. animations will help us accomplish this. The indicator will rotate while the content gets moves up or down then disapears. All of these should be done simultaneously and not sequentially. This task is easy thanks to Xamarin Forms animations.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | async void Close() { await Task.WhenAll( _accContent.TranslateTo(0, -10, AnimationDuration), _indicatorContainer.RotateTo(-180, AnimationDuration), _accContent.FadeTo(0, 50) ); _accContent.IsVisible = false; } async void Open() { _accContent.IsVisible = true; await Task.WhenAll( _accContent.TranslateTo(0, 10, AnimationDuration), _indicatorContainer.RotateTo(0, AnimationDuration), _accContent.FadeTo(30, 50, Easing.SinIn) ); } |
Using the Accordion
Usually, the accordion is depicted as a kind of list view whose items can collapse and open at will. But if you have been following, you might notice our accordion is just a single control. To make it appear in a list-like manner, you can set it as ItemTemplate for a collection view. Here is an example, followed by its visual representation.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <CollectionView Grid.Row="3"> <CollectionView.ItemsSource> .... .... </CollectionView. ItemsSource> <CollectionView.ItemTemplate> <DataTemplate> <local:Accordion Title="Todo"> <local:Accordion.AccordionContentView> <StackLayout> <CheckBox IsChecked="{Binding Done}"/> <Label Text="{Binding Title}" Margin="10"/> </StackLayout> </local:Accordion.AccordionContentView> <local:Accordion.IndicatorView> <Label Text="" FontSize="Large" FontFamily="{StaticResource FontAwesome}"/> </local:Accordion.IndicatorView> </local:Accordion> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> |
You might be interested about building a Snack Bar in Xamarin Forms. Or building a simple Edit Label in Xamarin Forms. These are other controls, you can find more the demos I do on Github.
If you find this article useful, please follow me on Twitter, Github, Linkedin, or like my Facebook page to stay updated.Follow me on social media and stay updated
Conclusion
Here you have a demo of how to create an accordion in Xamarin Forms. This control could be done in several other ways, and I’m interested to have your point of view in the comments. You can get the source code for this demo HERE
Follow me on social media and stay updated
Rik Bonhof