Introduction:
In Xamarin.Forms, there is no default RadioButton control available and we need to create our own custom RadioButton control. This article can explain you about to create RadioButton control and it's properties.
2. How to create RadioButton in Xamarin.Forms app?
<?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="RadioButtonSample.Views.HomePage"
xmlns:ctrls="clr-namespace:RadioButtonSample.Controls" >
<StackLayout Margin="20" x:Name="stackPanel">
<Label Text="Select Country" FontSize="25" FontAttributes="Bold" />
<ctrls:RadioButton x:Name="cbIndia" Title="India" IsChecked="True" BorderImageSource="radioborder" CheckedBackgroundImageSource="radiocheckedbg" CheckmarkImageSource="radiocheckmark" />
</StackLayout>
</ContentPage>
For example, if you want to use RadioButton from code behind.
In Xamarin.Forms, there is no default RadioButton control available and we need to create our own custom RadioButton control. This article can explain you about to create RadioButton control and it's properties.
Requirements:
- This article source code was prepared by using Visual Studio Community for Mac (7.3.2). And it is better to install latest visual studio updates from here.
- This sample project is Xamarin.Forms project and tested in Android emulator and iOS simulator.
Description:
This article can explain you below topics:
1. How to create Xamarin.Forms PCL project with Visual studio for Mac?
2. How to create RadioButton in Xamarin.Forms app?
3. How to use custom RadioButton in Xamarin.Forms?
1. How to create Xamarin.Forms PCL project with Visual studio for Mac?
Before to create RadioButton control, first we need to create the new Xamarin.Forms project.
- Launch Visual Studio for Mac.
- On the File menu, select New Solution.
- The New Project dialog appears. The left pane of the dialog lets you select the type of templates to display. In the left pane Multiplatform > App > Xamarin.Forms > Forms App and click on Next.
- Enter your App Name (Ex: RadioButtonSample). Select Target Platforms to Android & iOS and Shared Code to Portable Class Library after that click on Next button.
- You can choose your project location like below and Create new project.
2. How to create RadioButton in Xamarin.Forms app?
If you search for RadioButton in Xamarin.Forms in internet you will find more resources to create RadioButton and you may find mostly two answers like below
1. We can create our own RadioButton by inheriting ContentView.
2. We can use Nuget package library like XLabs.form. But this is having more bugs and is no longer maintained, and even says so on the github repo.
In this article, we are choosing first option to create RadioButton by inheriting ContentView. And please follow below few steps for the same
1. We can create our own RadioButton by inheriting ContentView.
2. We can use Nuget package library like XLabs.form. But this is having more bugs and is no longer maintained, and even says so on the github repo.
In this article, we are choosing first option to create RadioButton by inheriting ContentView. And please follow below few steps for the same
Step 1: Create ContentView
We are following default MVVM design pattern. And here we will place custom controls in Controls folder. So right click on your project name RadioButton Sample => Add => New Folder name is "Controls". After that right click on your newly created the folder => Add => New File => Forms => Forms ContentView Xaml and name it RadioButton.
Step 2: Add UI to RadioButton
In general, RadioButton control required major four elements.
Now open RadioButton.xaml and add below code.
Step 3: Add properties to RadioButton
We are going to add below Bindable properties for our RadioButton control.
Now open RadioButton.Xaml.cs and add below code.
4. How to use custom RadioButton in Xamarin.Forms?
- Title: Here we will take Label control to display title of RadioButton.
- Border: Here we will take one Image control that will hold BorderImageSource.
- Checkmark: Here we will take one Image control that will hold CheckMarkSource. And this check mark visibility should be based on user tap interaction which should deal by the some other property like IsChecked. I mean if IsChecked is True, check mark should be visible or else not visible.
- Background: Here we will take one Image control that will hold BackGroundImageSource
Now open RadioButton.xaml and add below code.
- <?xml version="1.0" encoding="UTF-8"?>
- <ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="RadioButtonSample.Controls.RadioButton">
- <ContentView.Content>
- <StackLayout Orientation="Horizontal"
- x:Name="mainContainer"
- HorizontalOptions="FillAndExpand"
- VerticalOptions="FillAndExpand"
- Padding="0"
- Spacing="5">
- <AbsoluteLayout HorizontalOptions="Center"
- VerticalOptions="Center"
- WidthRequest="20"
- HeightRequest="20"
- x:Name="imageContainer">
- <Image Source="{Binding CheckedBackgroundImageSource}"
- x:Name="checkedBackground"
- Aspect="AspectFit"
- AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"
- AbsoluteLayout.LayoutFlags="All"
- Opacity="0"
- InputTransparent="True"/>
- <Image Source="{Binding BorderImageSource}"
- x:Name="borderImage"
- Aspect="AspectFit"
- AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"
- AbsoluteLayout.LayoutFlags="All"
- InputTransparent="True"/>
- <Image Source="{Binding CheckmarkImageSource}"
- x:Name="checkedImage"
- Aspect="AspectFit"
- AbsoluteLayout.LayoutBounds="0.5, 0.5, 1, 1"
- AbsoluteLayout.LayoutFlags="All"
- Opacity="0"
- InputTransparent="True"/>
- </AbsoluteLayout>
- <Label x:Name="controlLabel"
- HorizontalOptions="FillAndExpand"
- VerticalOptions="FillAndExpand"
- HorizontalTextAlignment="Start"
- VerticalTextAlignment="Center"
- Text="{Binding Title}"
- Style="{Binding LabelStyle}"
- InputTransparent="True"/>
- </StackLayout>
- </ContentView.Content>
- </ContentView>
Step 3: Add properties to RadioButton
We are going to add below Bindable properties for our RadioButton control.
- TitleProperty: To bind tile of check box.
- LabelStyleProperty: To to set style to Title label.
- IsCheckedProperty: To maintain RadioButton states for check or uncheck.
- BorderImageSourceProperty: To set Border image for RadioButton.
- CheckedBackgroundImageSourceProperty:To set Background image for RadioButton.
- CheckMarkImageSourceProperty: To set CheckMark image for RadioButton.
- CheckedChangedCommandProperty: To make interaction with RadioButton when user tap on it's main container.
Now open RadioButton.Xaml.cs and add below code.
- using System;
- using System.Collections.Generic;
- using Xamarin.Forms;
- using Xamarin.Forms.Xaml;
- namespace RadioButtonSample.Controls
- {
- /// <summary>
- /// Custom RadioButton control
- /// </summary>
- [XamlCompilation(XamlCompilationOptions.Compile)]
- public partial class RadioButton : ContentView
- {
- public RadioButton()
- {
- InitializeComponent();
- controlLabel.BindingContext = this;
- checkedBackground.BindingContext = this;
- checkedImage.BindingContext = this;
- borderImage.BindingContext = this;
- mainContainer.GestureRecognizers.Add(new TapGestureRecognizer()
- {
- Command = new Command(tapped)
- });
- }
- public static readonly BindableProperty BorderImageSourceProperty = BindableProperty.Create(nameof(BorderImageSource), typeof(string), typeof(RadioButton), "", BindingMode.OneWay);
- public static readonly BindableProperty CheckedBackgroundImageSourceProperty = BindableProperty.Create(nameof(CheckedBackgroundImageSource), typeof(string), typeof(RadioButton), "", BindingMode.OneWay);
- public static readonly BindableProperty CheckmarkImageSourceProperty = BindableProperty.Create(nameof(CheckmarkImageSource), typeof(string), typeof(RadioButton), "", BindingMode.OneWay);
- public static readonly BindableProperty IsCheckedProperty = BindableProperty.Create(nameof(IsChecked), typeof(bool), typeof(RadioButton), false, BindingMode.TwoWay, propertyChanged: checkedPropertyChanged);
- public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(RadioButton), "", BindingMode.OneWay);
- public static readonly BindableProperty CheckedChangedCommandProperty = BindableProperty.Create(nameof(CheckedChangedCommand), typeof(Command), typeof(RadioButton), null, BindingMode.OneWay);
- public static readonly BindableProperty LabelStyleProperty = BindableProperty.Create(nameof(LabelStyle), typeof(Style), typeof(RadioButton), null, BindingMode.OneWay);
- public string BorderImageSource
- {
- get { return (string)GetValue(BorderImageSourceProperty); }
- set { SetValue(BorderImageSourceProperty, value); }
- }
- public string CheckedBackgroundImageSource
- {
- get { return (string)GetValue(CheckedBackgroundImageSourceProperty); }
- set { SetValue(CheckedBackgroundImageSourceProperty, value); }
- }
- public string CheckmarkImageSource
- {
- get { return (string)GetValue(CheckmarkImageSourceProperty); }
- set { SetValue(CheckmarkImageSourceProperty, value); }
- }
- public bool IsChecked
- {
- get { return (bool)GetValue(IsCheckedProperty); }
- set { SetValue(IsCheckedProperty, value); }
- }
- public string Title
- {
- get { return (string)GetValue(TitleProperty); }
- set { SetValue(TitleProperty, value); }
- }
- public Command CheckedChangedCommand
- {
- get { return (Command)GetValue(CheckedChangedCommandProperty); }
- set { SetValue(CheckedChangedCommandProperty, value); }
- }
- public Style LabelStyle
- {
- get { return (Style)GetValue(LabelStyleProperty); }
- set { SetValue(LabelStyleProperty, value); }
- }
- public Label ControlLabel
- {
- get { return controlLabel; }
- }
- static void checkedPropertyChanged(BindableObject bindable, object oldValue, object newValue)
- {
- ((RadioButton)bindable).ApplyCheckedState();
- }
- void tapped()
- {
- if (!IsChecked)
- IsChecked = true;
- setCheckedState(IsChecked);
- if (CheckedChangedCommand != null && CheckedChangedCommand.CanExecute(this))
- CheckedChangedCommand.Execute(this);
- }
- /// <summary>
- /// Reflect the checked event change on the UI
- /// with a small animation
- /// </summary>
- /// <param name="isChecked"></param>
- void setCheckedState(bool isChecked)
- {
- Animation storyboard = new Animation();
- Animation fadeAnim = null;
- Animation checkBounceAnim = null;
- Animation checkFadeAnim = null;
- double fadeStartVal = 0;
- double fadeEndVal = 1;
- double scaleStartVal = 0;
- double scaleEndVal = 1;
- Easing checkEasing = Easing.CubicIn;
- if (isChecked)
- {
- checkedImage.Scale = 0;
- fadeStartVal = 0;
- fadeEndVal = 1;
- scaleStartVal = 0;
- scaleEndVal = 1;
- checkEasing = Easing.CubicIn;
- }
- else
- {
- fadeStartVal = 1;
- fadeEndVal = 0;
- scaleStartVal = 1;
- scaleEndVal = 0;
- checkEasing = Easing.CubicOut;
- }
- fadeAnim = new Animation(
- callback: d => checkedBackground.Opacity = d,
- start: fadeStartVal,
- end: fadeEndVal,
- easing: Easing.CubicOut
- );
- checkFadeAnim = new Animation(
- callback: d => checkedImage.Opacity = d,
- start: fadeStartVal,
- end: fadeEndVal,
- easing: checkEasing
- );
- checkBounceAnim = new Animation(
- callback: d => checkedImage.Scale = d,
- start: scaleStartVal,
- end: scaleEndVal,
- easing: checkEasing
- );
- storyboard.Add(0, 0.6, fadeAnim);
- storyboard.Add(0, 0.6, checkFadeAnim);
- storyboard.Add(0.4, 1, checkBounceAnim);
- storyboard.Commit(this, "checkAnimation", length: 600);
- }
- public void ApplyCheckedState()
- {
- setCheckedState(IsChecked);
- }
- }
- }
4. How to use custom RadioButton in Xamarin.Forms?
Now we are ready to our own RadioButton control. Before to use it, let's create one ContentPage in Views folder.
To create page, right click on Views folder => Add =>New File => Forms => Forms ContentPage Xaml and name it HomePage like below.
To use RadioButton in our xaml page. First we need declare namespace of RadioButton.
- xmlns:ctrls="clr-namespace:RadioButtonSample.Controls"
And then we can use RadioButton like below
- <ctrls:RadioButton x:Name="cbIndia" Title="India" IsChecked="True" BorderImageSource="radioborder" CheckedBackgroundImageSource="radiocheckedbg" CheckmarkImageSource="radiocheckmark" />
Here we set the values for the RadioButton properties are
Title: India
IsChecked: True
BorderImageSource: radioborder.png
CheckBackgroundImageSource: radiocheckedbg.png
CheckmarkImageSource: radiocheckmark.png
We should add all above images to Android drawable folder and for iOS Resources folder.
Now open HomePage.xaml file, add below total source code.
- void CreateRadioButton()
- {
- RadioButton radioButton = new RadioButton();
- radioButton.IsChecked = false;
- radioButton.IsVisible = true;
- radioButton.Title = "Japan";
- radioButton.BorderImageSource = "radioborder";
- radioButton.CheckedBackgroundImageSource = "radiocheckedbg";
- radioButton.CheckmarkImageSource = "radiocheckmark";
- stackPanel.Children.Add(radioButton);
- }
For example, if you want to bind RadioButton from code behind.
- void RadioButtonBinding()
- {
- Country country = new Country();
- country.Name = "Singapore";
- country.IsSelected = false;
- country.IsVisible = true;
- RadioButton radioButton = new RadioButton();
- radioButton.BindingContext = country;
- radioButton.SetBinding(RadioButton.IsCheckedProperty, "IsSelected", BindingMode.TwoWay);
- radioButton.SetBinding(RadioButton.IsVisibleProperty, "IsVisible");
- radioButton.SetBinding(RadioButton.TitleProperty, "Name");
- radioButton.BorderImageSource = "radioborder";
- radioButton.CheckedBackgroundImageSource = "radiocheckedbg";
- radioButton.CheckmarkImageSource = "radiocheckmark";
- stackPanel.Children.Add(radioButton);
- }
In above code, we bind the RadioButton with Country class object properties (Name, IsSelected, IsVisibile). So let's create Country Class in Model folder. To create class, right click on Models folder => Add =>New File => General => Empty Class and name it Country like below.
Now open Country class and add below properties.
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Runtime.CompilerServices;
- namespace RadioButtonSample
- {
- public class Country: INotifyPropertyChanged
- {
- public string Name { get; set; }
- bool isVisible;
- public bool IsVisible
- {
- get { return isVisible; }
- set { SetProperty(ref isVisible, value); }
- }
- bool isSelected;
- public bool IsSelected
- {
- get { return isSelected; }
- set { SetProperty(ref isSelected, value); }
- }
- protected bool SetProperty<T>(ref T backingStore, T value,
- [CallerMemberName]string propertyName = "",
- Action onChanged = null)
- {
- if (EqualityComparer<T>.Default.Equals(backingStore, value))
- return false;
- backingStore = value;
- onChanged?.Invoke();
- OnPropertyChanged(propertyName);
- return true;
- }
- #region INotifyPropertyChanged
- public event PropertyChangedEventHandler PropertyChanged;
- protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
- {
- var changed = PropertyChanged;
- if (changed == null)
- return;
- changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- #endregion
- }
- }
Let's see overview of total source code of HopePage.xaml.cs file.
- using RadioButtonSample.Controls;
- using RadioButtonSample.ViewModels;
- using Xamarin.Forms;
- namespace RadioButtonSample.Views
- {
- public partial class HomePage : ContentPage
- {
- HomeViewModel _homeViewModel;
- public HomePage()
- {
- InitializeComponent();
- CreateRadioButton();
- RadioButtonBinding();
- }
- /// <summary>
- /// Creating RadioButton with assigned values (Bg, border, title, selection)
- /// </summary>
- void CreateRadioButton()
- {
- RadioButton radioButton = new RadioButton();
- radioButton.IsChecked = false;
- radioButton.IsVisible = true;
- radioButton.Title = "Japan";
- radioButton.BorderImageSource = "radioborder";
- radioButton.CheckedBackgroundImageSource = "radiocheckedbg";
- radioButton.CheckmarkImageSource = "radiocheckmark";
- stackPanel.Children.Add(radioButton);
- }
- /// <summary>
- /// RadioButton binding with homeViewModel
- /// </summary>
- void RadioButtonBinding()
- {
- Country country = new Country();
- country.Name = "Singapore";
- country.IsSelected = false;
- country.IsVisible = true;
- RadioButton radioButton = new RadioButton();
- radioButton.BindingContext = country;
- radioButton.SetBinding(RadioButton.IsCheckedProperty, "IsSelected", BindingMode.TwoWay);
- radioButton.SetBinding(RadioButton.IsVisibleProperty, "IsVisible");
- radioButton.SetBinding(RadioButton.TitleProperty, "Name");
- radioButton.BorderImageSource = "radioborder";
- radioButton.CheckedBackgroundImageSource = "radiocheckedbg";
- radioButton.CheckmarkImageSource = "radiocheckmark";
- stackPanel.Children.Add(radioButton);
- }
- }
- }
Demo Screens from Android:
Demo Screens from iOS:
You can directly work on below sample source code to understand the this article.
FeedBack Note: Please share your thoughts, what you think about this post, Is this post really helpful for you? Otherwise, it would be very happy, if you have any thoughts for to implement this requirement in any other way? I always welcome if you drop comments on this post and it would be impressive.
Hello, would you be so kind and provide me images you used in the exampla? Thank you.
ReplyDeleteI would also like to have the image files. Thank you.
DeleteHi, great code, thanks for sharing.
ReplyDeleteCould you tell me how can I set (to a smaller one) the font size of the radio buttons title?
only one radio button can select at once. How to achieve that?
ReplyDeleteDid you get response?
Deleteif (sender is YourListview lv) lv.SelectedItem = null;
DeleteYourModel obj = new YourModel ();
obj.SortingData = ((Grid)sender).ClassId;
foreach (YourModel item in YourList.ToList())
{
try
{
//selected property of Radio Button
item.Selected = false;
if (item.SortingData == obj.SortingData)
{
item.Selected = true;
}
}
catch (Exception ex)
{
DisplayAlert("", ex.Message, "ok");
}