{"id":48476,"date":"2021-01-29T10:00:58","date_gmt":"2021-01-29T18:00:58","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/xamarin\/?p=48476"},"modified":"2021-01-28T14:08:58","modified_gmt":"2021-01-28T22:08:58","slug":"beautiful-custom-radiobutton-with-xamarin-forms-5","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/beautiful-custom-radiobutton-with-xamarin-forms-5\/","title":{"rendered":"Beautiful Custom RadioButton with Xamarin.Forms 5"},"content":{"rendered":"<p>This weekend I was looking to update my settings page on my latest app, <a href=\"https:\/\/montemagno.com\/introducing-my-cadence-for-ios-a-simple-cadence-sensor-display\/\">My Cadence<\/a>, and introduce a new option to allow the user to select a default theme for their application. There are a few ways to implement this features. In previous applications I have built, I have used the <a href=\"https:\/\/docs.microsoft.com\/xamarin\/xamarin-forms\/user-interface\/picker\/?WT.mc_id=friends-0000-jamont\">Picker<\/a> control to give users the option to pick a setting:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/xamarin\/wp-content\/uploads\/sites\/44\/2021\/01\/picker-control.png\" alt=\"Picker control showing a list of theme options\" \/><\/p>\n<p>This is a pretty good experience, however I wanted to see if there was something new in <a href=\"https:\/\/devblogs.microsoft.com\/xamarin\/xamarin-forms-5-0-is-here\/?WT.mc_id=friends-0000-jamont\">Xamarin.Forms 5<\/a> that I could leverage to create a better experience. Browsing the <a href=\"https:\/\/docs.microsoft.com\/xamarin\/whats-new\/2021-01?WT.mc_id=friends-0000-jamont\">documentation<\/a> I stumbled upon the brand new <a href=\"https:\/\/devblogs.microsoft.com\/xamarin\/xamarin-forms-5-0-is-here\/?WT.mc_id=friends-0000-jamont\">RadioButton<\/a> control that is fully templatable! This means you can completely customize the look and feel of the control while still maintaining the functionality of the control.<\/p>\n<p>So, let&#8217;s take a look at how to leverage this new feature to create a new way for my users to select the theme.<\/p>\n<h2>Enter RadioButton!<\/h2>\n<p>The first thing to do is to add the RadioButton to your application. To create a theme selection UI we will create a <code>Grid<\/code> with 3 columns each with a <code>RadioButton<\/code> in it.<\/p>\n<pre><code class=\"xml\">&lt;Grid\n    ColumnDefinitions=\"*,*,*\"\n    ColumnSpacing=\"10\"&gt;\n    &lt;RadioButton IsChecked=\"True\" Content=\"System Default\"\/&gt;\n    &lt;RadioButton Grid.Column=\"1\" Content=\"Light\"\/&gt;\n    &lt;RadioButton Grid.Column=\"2\" Content=\"Dark\"\/&gt;\n&lt;\/Grid&gt;\n<\/code><\/pre>\n<p>This will result with the default control that displays the RadioButton besides text.<\/p>\n<p><center>\n  <img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/xamarin\/wp-content\/uploads\/sites\/44\/2021\/01\/default.png\" alt=\"Default radio buttons with text\" \/>\n<\/center><\/p>\n<p>One of the beautiful parts of the new RadioButton is that it has <a href=\"https:\/\/docs.microsoft.com\/xamarin\/xamarin-forms\/app-fundamentals\/templates\/control-template?WT.mc_id=friends-0000-jamont\">control templating<\/a> built in. This means you can override the default template that is a <code>Label<\/code> with anything!<\/p>\n<h2>Control Template<\/h2>\n<p>In our <code>ContentPage.Resources<\/code> we can add a new control template that can be applied to the <code>RadioButton<\/code>. It controls what the <code>RadioButton<\/code> looks like and even has access to the <code>VisualStateManager<\/code> so we can customize what the <code>Checked<\/code> state looks like. Now, this is a bit of code, but what we are creating in a template where we are drawing the circle in the top right of a frame that has a <code>ContentPresenter<\/code> in the main area in which we can fill in any UI we want.<\/p>\n<pre><code class=\"xml\">   &lt;ContentPage.Resources&gt;\n        &lt;ResourceDictionary&gt;\n\n            &lt;Color x:Key=\"LightRadioButtonColor\"&gt;#F3F2F1&lt;\/Color&gt;\n            &lt;Color x:Key=\"DarkRadioButtonColor\"&gt;#9B9A99&lt;\/Color&gt;\n\n            &lt;ControlTemplate x:Key=\"ThemeRadioTemplate\"&gt;\n                &lt;Frame\n                    Padding=\"0\"\n                    BackgroundColor=\"{AppThemeBinding Dark={StaticResource DarkRadioButtonColor},\n                                                      Light={StaticResource LightRadioButtonColor}}\"\n                    BorderColor=\"{AppThemeBinding Dark={StaticResource DarkRadioButtonColor},\n                                                  Light={StaticResource LightRadioButtonColor}}\"\n                    HasShadow=\"False\"\n                    HeightRequest=\"80\"\n                    HorizontalOptions=\"Start\"\n                    VerticalOptions=\"Start\"\n                    WidthRequest=\"80\"&gt;\n                    &lt;Grid Margin=\"4\" WidthRequest=\"80\"&gt;\n                        &lt;Grid\n                            HeightRequest=\"20\"\n                            HorizontalOptions=\"End\"\n                            VerticalOptions=\"Start\"\n                            WidthRequest=\"20\"&gt;\n                            &lt;Ellipse\n                                Fill=\"White\"\n                                HeightRequest=\"18\"\n                                HorizontalOptions=\"Center\"\n                                Stroke=\"#2E2545\"\n                                StrokeThickness=\"1\"\n                                VerticalOptions=\"Center\"\n                                WidthRequest=\"18\" \/&gt;\n                            &lt;Ellipse\n                                x:Name=\"Check\"\n                                BackgroundColor=\"Transparent\"\n                                Fill=\"#df6e57\"\n                                HeightRequest=\"10\"\n                                HorizontalOptions=\"Center\"\n                                Stroke=\"#df6e57\"\n                                StrokeThickness=\"0\"\n                                VerticalOptions=\"Center\"\n                                WidthRequest=\"10\" \/&gt;\n                        &lt;\/Grid&gt;\n                        &lt;!-- This enables us to put in dynamic content --&gt;\n                        &lt;ContentPresenter \/&gt;\n                    &lt;\/Grid&gt;\n                    &lt;VisualStateManager.VisualStateGroups&gt;\n                        &lt;VisualStateGroupList&gt;\n                            &lt;VisualStateGroup x:Name=\"CheckedStates\"&gt;\n                                &lt;VisualState x:Name=\"Checked\"&gt;\n                                    &lt;VisualState.Setters&gt;\n                                        &lt;Setter Property=\"BorderColor\" Value=\"#df6e57\" \/&gt;\n                                        &lt;Setter TargetName=\"Check\" Property=\"Opacity\" Value=\"1\" \/&gt;\n                                    &lt;\/VisualState.Setters&gt;\n                                &lt;\/VisualState&gt;\n                                &lt;VisualState x:Name=\"Unchecked\"&gt;\n                                    &lt;VisualState.Setters&gt;\n                                        &lt;Setter Property=\"BorderColor\" Value=\"#F3F2F1\" \/&gt;\n                                        &lt;Setter TargetName=\"Check\" Property=\"Opacity\" Value=\"0\" \/&gt;\n                                    &lt;\/VisualState.Setters&gt;\n                                &lt;\/VisualState&gt;\n                            &lt;\/VisualStateGroup&gt;\n                        &lt;\/VisualStateGroupList&gt;\n                    &lt;\/VisualStateManager.VisualStateGroups&gt;\n                &lt;\/Frame&gt;\n            &lt;\/ControlTemplate&gt;\n        &lt;\/ResourceDictionary&gt;\n    &lt;\/ContentPage.Resources&gt;\n<\/code><\/pre>\n<p>We can now apply this template to each <code>RadioButton<\/code>. It will continue to use our text label content but apply the control template that we just setup.<\/p>\n<pre><code class=\"xml\">&lt;Grid ColumnDefinitions=\"*,*,*\" ColumnSpacing=\"10\"&gt;\n    &lt;RadioButton ControlTemplate=\"{StaticResource ThemeRadioTemplate}\" Content=\"Default\" IsChecked=\"True\" \/&gt;\n    &lt;RadioButton ControlTemplate=\"{StaticResource ThemeRadioTemplate}\" Grid.Column=\"1\" Content=\"Light\" \/&gt;\n    &lt;RadioButton ControlTemplate=\"{StaticResource ThemeRadioTemplate}\" Grid.Column=\"2\" Content=\"Dark\" \/&gt;\n&lt;\/Grid&gt;\n<\/code><\/pre>\n<p><center>\n  <img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/xamarin\/wp-content\/uploads\/sites\/44\/2021\/01\/template-default.png\" alt=\"Radio buttons using template with just labels\" \/>\n<\/center><\/p>\n<p>We aren&#8217;t done though as we can now leverage the <code>ContentPresenter<\/code> and set the <code>Content<\/code> to anything that we want. For this UI I want to put in an Image (in this case a FontAwesome label) and text on the bottom.<\/p>\n<pre><code class=\"xml\">&lt;RadioButton.Content&gt;\n    &lt;StackLayout HorizontalOptions=\"Center\" VerticalOptions=\"Center\"&gt;\n        &lt;Image Scale=\"0.75\" Source=\"{FontImage FontFamily=FA, Glyph={x:Static helpers:FAIcons.UserCog}, Color=#323130}\" \/&gt;\n        &lt;Label FontSize=\"Small\" Text=\"System\" TextColor=\"#323130\" \/&gt;\n    &lt;\/StackLayout&gt;\n&lt;\/RadioButton.Content&gt;\n<\/code><\/pre>\n<p>The full XAML for all three <code>RadioButton<\/code> controls would look a bit like this:<\/p>\n<pre><code class=\"xml\">&lt;RadioButton ControlTemplate=\"{StaticResource ThemeRadioTemplate}\" IsChecked=\"True\"&gt;\n    &lt;RadioButton.Content&gt;\n        &lt;StackLayout HorizontalOptions=\"Center\" VerticalOptions=\"Center\"&gt;\n            &lt;Image Scale=\"0.75\" Source=\"{FontImage FontFamily=FA, Glyph={x:Static helpers:FAIcons.UserCog}, Color=#323130}\" \/&gt;\n            &lt;Label FontSize=\"Small\" Text=\"System\" TextColor=\"#323130\" \/&gt;\n        &lt;\/StackLayout&gt;\n    &lt;\/RadioButton.Content&gt;\n&lt;\/RadioButton&gt;\n&lt;RadioButton ControlTemplate=\"{StaticResource ThemeRadioTemplate}\" Grid.Column=\"1\"&gt;\n    &lt;RadioButton.Content&gt;\n        &lt;StackLayout HorizontalOptions=\"Center\" VerticalOptions=\"Center\"&gt;\n            &lt;Image Scale=\"0.75\" Source=\"{FontImage FontFamily=FA, Glyph={x:Static helpers:FAIcons.Sun}, Color=#323130}\" \/&gt;\n            &lt;Label FontSize=\"Small\" Text=\"Light\" TextColor=\"#323130\" \/&gt;\n        &lt;\/StackLayout&gt;\n    &lt;\/RadioButton.Content&gt;\n&lt;\/RadioButton&gt;\n&lt;RadioButton ControlTemplate=\"{StaticResource ThemeRadioTemplate}\" Grid.Column=\"2\"&gt;\n    &lt;RadioButton.Content&gt;\n        &lt;StackLayout HorizontalOptions=\"Center\" VerticalOptions=\"Center\"&gt;\n            &lt;Image Scale=\"0.75\" Source=\"{FontImage FontFamily=FA, Glyph={x:Static helpers:FAIcons.Moon}, Color=#323130}\" \/&gt;\n            &lt;Label FontSize=\"Small\" Text=\"Dark\" TextColor=\"#323130\" \/&gt;\n        &lt;\/StackLayout&gt;\n    &lt;\/RadioButton.Content&gt;\n&lt;\/RadioButton&gt;\n<\/code><\/pre>\n<p>This will result in great cross-platform custom <code>RadioButton<\/code>!<\/p>\n<p><center>\n  <img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/xamarin\/wp-content\/uploads\/sites\/44\/2021\/01\/final.png\" alt=\"Final radio buttons with icons and text\" \/>\n<\/center><\/p>\n<h2>Learn More<\/h2>\n<p>Checkout the full documentation for <a href=\"https:\/\/docs.microsoft.com\/xamarin\/xamarin-forms\/user-interface\/radiobutton?WT.mc_id=friends-0000-jamont\">RadioButton<\/a> and also <a href=\"https:\/\/docs.microsoft.com\/xamarin\/xamarin-forms\/app-fundamentals\/templates\/control-template?WT.mc_id=friends-0000-jamont\">control templating<\/a> for more insight on how to implement this in your app.<\/p>\n<p>You can also browse the source code of <a href=\"https:\/\/github.com\/davidortinau\/losgatos?WT.mc_id=friends-0000-jamont\">LosGatos on GitHub<\/a>, which is a delightful sample from David Ortinau that uses this technique.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Xamarin.Forms 5 introduced control templates for the new RadioButton control that gives you complete control and customization over the user interface.<\/p>\n","protected":false},"author":544,"featured_media":48477,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2,1,367],"tags":[9193,9194,9168],"class_list":["post-48476","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","category-xamarin","category-xamarin-forms","tag-control-template","tag-radio-button","tag-xamarin-forms-5"],"acf":[],"blog_post_summary":"<p>Xamarin.Forms 5 introduced control templates for the new RadioButton control that gives you complete control and customization over the user interface.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/48476","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/544"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=48476"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/48476\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/48477"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=48476"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=48476"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=48476"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}