Many users of JQuery UI (both Mobile as well as web) are quite fond of accordion user control and ask for the same or a similar kind of control in Xamarin/ Xamarin Forms. As we all know that Xamarin forms controls are an abstraction to the native controls available in respective native platforms and since there is no accordion control available in any of the native mobile frameworks it’s not available as an out-of-the-box control in Xamarin Forms. So in this article we will be creating a simple accordion user-control using simple Xamarin Forms controls like Button and ContentView.
Firstly, we need to understand the functionality of an accordion, as per Wikipedia the developer's definition of an accordion is:
Several buttons or labels are stacked upon one another. At most one of them can be “active”. When a button is active the space below the button is used to display a paned window. The pane is usually constrained by the width of labels. When opened it shifts labels under the clicked label down according to the height of that window. Only one button or pane combination can be active at any one time; when a button is selected any other active panes cease to be active and are hidden. The active pane may have scrollbars.
The ‘Accordion’ class is extended from ContentView class of Xamarin; forms in which I am creating an accordion from list ‘AccordianSource’ objects on DataBind Method of the Class. The code of ‘Accordion’ user control is as follows:
- public class Accordion: ContentView
- {
- #region Private Variables
- List < AccordionSource > mDataSource;
- bool mFirstExpaned = false;
- StackLayout mMainLayout;
- #endregion
- public Accordion()
- {
- var mMainLayout = new StackLayout();
- Content = mMainLayout;
- }
- public Accordion(List < AccordionSource > aSource)
- {
- mDataSource = aSource;
- DataBind();
- }
- #region Properties
- public List < AccordionSource > DataSource
- {
- get
- {
- return mDataSource;
- }
- set
- {
- mDataSource = value;
- }
- }
- public bool FirstExpaned
- {
- get
- {
- return mFirstExpaned;
- }
- set
- {
- mFirstExpaned = value;
- }
- }
- #endregion
- public void DataBind()
- {
- var vMainLayout = new StackLayout();
- var vFirst = true;
- if (mDataSource != null)
- {
- foreach(var vSingleItem in mDataSource)
- {
- var vHeaderButton = new AccordionButton()
- {
- Text = vSingleItem.HeaderText,
- TextColor = vSingleItem.HeaderTextColor,
- BackgroundColor = vSingleItem.HeaderBackGroundColor
- };
- var vAccordionContent = new ContentView()
- {
- Content = vSingleItem.ContentItems,
- IsVisible = false
- };
- if (vFirst)
- {
- vHeaderButton.Expand = mFirstExpaned;
- vAccordionContent.IsVisible = mFirstExpaned;
- vFirst = false;
- }
- vHeaderButton.AssosiatedContent = vAccordionContent;
- vHeaderButton.Clicked += OnAccordionButtonClicked;
- vMainLayout.Children.Add(vHeaderButton);
- vMainLayout.Children.Add(vAccordionContent);
- }
- }
- mMainLayout = vMainLayout;
- Content = mMainLayout;
- }
- void OnAccordionButtonClicked(object sender, EventArgs args)
- {
- foreach(var vChildItem in mMainLayout.Children)
- {
- if (vChildItem.GetType() == typeof(ContentView)) vChildItem.IsVisible = false;
- if (vChildItem.GetType() == typeof(AccordionButton))
- {
- var vButton = (AccordionButton) vChildItem;
- vButton.Expand = false;
- }
- }
- var vSenderButton = (AccordionButton) sender;
- if (vSenderButton.Expand)
- {
- vSenderButton.Expand = false;
- }
- else vSenderButton.Expand = true;
- vSenderButton.AssosiatedContent.IsVisible = vSenderButton.Expand;
- }
- }
- using System;
- public class AccordionSource
- {
- public string HeaderText
- {
- get;
- set;
- }
- public Color HeaderTextColor
- {
- get;
- set;
- }
- public Color HeaderBackGroundColor
- {
- get;
- set;
- }
- public View ContentItems
- {
- get;
- set;
- }
- }
- public class AccordionButton: Button {
- #region Private Variables
- bool mExpand = false;
- #endregion
- public AccordionButton() {
- HorizontalOptions = LayoutOptions.FillAndExpand;
- BorderColor = Color.Black;
- BorderRadius = 5;
- BorderWidth = 0;
- }#region Properties
- public bool Expand {
- get {
- return mExpand;
- }
- set {
- mExpand = value;
- }
- }
- public ContentView AssosiatedContent {
- get;
- set;
- }#endregion
- }
The ‘XamlExample’ page have used this control using following code in XAML:
- <?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:ctrl="clr-namespace:AccordionEx;assembly=AccordionEx" x:Class="AccordionEx.XamlExample" Title="XAML Example">
- <ContentPage.Content>
- <ctrl:Accordion x:Name="MainOne" />
- </ContentPage.Content>
- </ContentPage>
- public XamlExample ()
- {
- InitializeComponent ();
- MainOne.DataSource = GetSampleData ();
- MainOne.DataBind ();
- }
- public CodeEaxmple()
- {
- Title = "Code Example";
- var vAccordionSource = GetSampleData();
- var vAccordionControl = new Accordion(vAccordionSource);
- Content = vAccordionControl;
- }
- public List < AccordionSource > GetSampleData()
- {
- var vResult = new List < AccordionSource > ();
- #region First List View
- var vListOne = new List < SimpleObject > ();
- for (var iCount = 0; iCount < 6; iCount++)
- {
- var vObject = new SimpleObject()
- {
- TextValue = "ObjectNo-" + iCount.ToString(),
- DataValue = iCount.ToString()
- };
- vListOne.Add(vObject);
- }
- var vListViewOne = new ListView()
- {
- ItemsSource = vListOne,
- ItemTemplate = new DataTemplate(typeof(ListDataViewCell))
- };
- vListViewOne.ItemTapped += OnListItemClicked;
- #endregion# region Second List
- var vListTwo = new List < SimpleObject > ();
- var vObjectRavi = new SimpleObject()
- {
- TextValue = "S Ravi Kumar",
- DataValue = "1"
- };
- vListTwo.Add(vObjectRavi);
- var vObjectFather = new SimpleObject()
- {
- TextValue = "Father",
- DataValue = "2"
- };
- vListTwo.Add(vObjectFather);
- var vObjectTrainer = new SimpleObject()
- {
- TextValue = "Trainer",
- DataValue = "2"
- };
- vListTwo.Add(vObjectTrainer);
- var vObjectConsultant = new SimpleObject()
- {
- TextValue = "Consultant",
- DataValue = "2"
- };
- vListTwo.Add(vObjectConsultant);
- var vObjectArchitect = new SimpleObject()
- {
- TextValue = "Architect",
- DataValue = "2"
- };
- vListTwo.Add(vObjectArchitect);
- var vListViewTwo = new ListView()
- {
- ItemsSource = vListTwo,
- ItemTemplate = new DataTemplate(typeof(ListDataViewCell))
- };
- vListViewTwo.ItemTapped += OnListItemClicked;
- #endregion
- #region StackLayout
- var vViewLayout = new StackLayout()
- {
- Children = {
- new Label
- {
- Text = "Static Content:"
- },
- new Label
- {
- Text = "Name : S Ravi Kumar"
- },
- new Label
- {
- Text = "Roles : Father,Trainer,Consultant,Architect"
- }
- }
- };
- #endregion
- var vFirstAccord = new AccordionSource()
- {
- HeaderText = "First",
- HeaderTextColor = Color.Black,
- HeaderBackGroundColor = Color.Yellow,
- ContentItems = vListViewTwo
- };
- vResult.Add(vFirstAccord);
- var vSecond = new AccordionSource()
- {
- HeaderText = "Second ",
- HeaderTextColor = Color.White,
- HeaderBackGroundColor = Color.FromHex("#77d065"),
- ContentItems = vViewLayout
- };
- vResult.Add(vSecond);
- var vThird = new AccordionSource()
- {
- HeaderText = "Third",
- HeaderTextColor = Color.White,
- HeaderBackGroundColor = Color.Purple,
- ContentItems = vListViewOne
- };
- vResult.Add(vThird);
- return vResult;
- }
The code of ‘ListDataViewCell’ and ‘SimpleObject’ class are as follows:
- public class ListDataViewCell: ViewCell
- {
- public ListDataViewCell()
- {
- var label = new Label()
- {
- Font = Font.SystemFontOfSize(NamedSize.Default),
- TextColor = Color.Blue
- };
- label.SetBinding(Label.TextProperty, new Binding("TextValue"));
- label.SetBinding(Label.ClassIdProperty, new Binding("DataValue"));
- View = new StackLayout()
- {
- Orientation = StackOrientation.Vertical,
- VerticalOptions = LayoutOptions.StartAndExpand,
- Padding = new Thickness(12, 8),
- Children = {
- label
- }
- };
- }
- }
- public class SimpleObject
- {
- public string TextValue
- {
- get;
- set;
- }
- public string DataValue
- {
- get;
- set;
- }
- }
XAML Code:
- <?xml version="1.0" encoding="UTF-8"?>
- <ContentPage
- xmlns="http://xamarin.com/schemas/2014/forms"
- xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="AccordionEx.HomePage" Title="Accordion Example" >
- <ContentPage.Resources>
- <ResourceDictionary>
- <Style TargetType="Button">
- <Setter Property="BorderRadius" Value="10" />
- <Setter Property="BorderWidth" Value="2" />
- <Setter Property="WidthRequest" Value="150" />
- <Setter Property="HeightRequest" Value="150" />
- <Setter Property="HorizontalOptions" Value="Center" />
- <Setter Property="VerticalOptions" Value="Center" />
- <Setter Property="FontSize" Value="Medium" />
- <Setter Property="TextColor" Value="Red" />
- </Style>
- </ResourceDictionary>
- </ContentPage.Resources>
- <ContentPage.Content>
- <StackLayout VerticalOptions = "Center">
- <Button Text="Xaml Page" Clicked="OnXamlClicked" />
- <Button Text="Code Page" Clicked="OnCodeClicked" />
- </StackLayout>
- </ContentPage.Content>
- </ContentPage>
- public partial class HomePage: ContentPage
- {
- public HomePage()
- {
- InitializeComponent();
- }
- public void OnXamlClicked(object sender, EventArgs args)
- {
- Navigation.PushAsync(new XamlExample());
- }
- public void OnCodeClicked(object sender, EventArgs args)
- {
- Navigation.PushAsync(new CodeEaxmple());
- }
- }
- public App ()
- {
- // The root page of your application
- MainPage = new NavigationPage(new HomePage());
- }

Xamarin Android Player:

The source code of sample application containing accordion user control and pages using the control can be downloaded from Github.

manohar bonalaPosted May 3, 2017, 9:06 AM
Is there any way to limit the listview height as it is occupying more space than it is required. so i am getting some extra empty space at the end
Cesar RobledoPosted Oct 25, 2016, 4:32 PM
I have a problem that throws me is this: Unhandled Exception: System.InvalidOperationException: Cannot convert "S Ravi Kumar" into Xamarin.Forms.Color
Manoj KulkarniPosted Apr 11, 2016, 1:47 AM
Nice
Asfend YarPosted Mar 27, 2016, 5:27 AM
good
Humayun Kabir MamunPosted Mar 27, 2016, 12:53 AM
Nice...
Kashif SohailPosted Mar 26, 2016, 11:34 PM
Exctly the thing i was looking for
Vignesh ManiPosted Mar 26, 2016, 8:53 AM
nice one
Mahesh ChandPosted Mar 26, 2016, 1:11 AM
Welcome to C# Corner, S. Ravi.
Debasis SahaPosted Mar 26, 2016, 12:40 AM
Nice one..
Sibeesh VenuPosted Mar 26, 2016, 12:33 AM
That's a good one.
Kumaresh RajalingamPosted Mar 25, 2016, 9:47 PM
Good stuff
Joginder BangerPosted Mar 25, 2016, 5:00 PM
sir What i used phone native function ...like camera phone book and so on....
Ammar ShaukatPosted Mar 25, 2016, 4:38 PM
Awesome. really good work bhai