7

Beautiful Custom RadioButton with Xamarin.Forms 5

 3 years ago
source link: https://devblogs.microsoft.com/xamarin/beautiful-custom-radiobutton-with-xamarin-forms-5/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Beautiful Custom RadioButton with Xamarin.Forms 5

Beautiful Custom RadioButton with Xamarin.Forms 5

Avatar

James

January 29th, 2021

This weekend I was looking to update my settings page on my latest app, My Cadence, 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 Picker control to give users the option to pick a setting:

This is a pretty good experience, however I wanted to see if there was something new in Xamarin.Forms 5 that I could leverage to create a better experience. Browsing the documentation I stumbled upon the brand new RadioButton 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.

So, let’s take a look at how to leverage this new feature to create a new way for my users to select the theme.

Enter RadioButton!

The first thing to do is to add the RadioButton to your application. To create a theme selection UI we will create a Grid with 3 columns each with a RadioButton in it.

<Grid
    ColumnDefinitions="*,*,*"
    ColumnSpacing="10">
    <RadioButton IsChecked="True" Content="System Default"/>
    <RadioButton Grid.Column="1" Content="Light"/>
    <RadioButton Grid.Column="2" Content="Dark"/>
</Grid>

This will result with the default control that displays the RadioButton besides text.

One of the beautiful parts of the new RadioButton is that it has control templating built in. This means you can override the default template that is a Label with anything!

Control Template

In our ContentPage.Resources we can add a new control template that can be applied to the RadioButton. It controls what the RadioButton looks like and even has access to the VisualStateManager so we can customize what the Checked 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 ContentPresenter in the main area in which we can fill in any UI we want.

   <ContentPage.Resources>
        <ResourceDictionary>

            <Color x:Key="LightRadioButtonColor">#F3F2F1</Color>
            <Color x:Key="DarkRadioButtonColor">#9B9A99</Color>

            <ControlTemplate x:Key="ThemeRadioTemplate">
                <Frame
                    Padding="0"
                    BackgroundColor="{AppThemeBinding Dark={StaticResource DarkRadioButtonColor},
                                                      Light={StaticResource LightRadioButtonColor}}"
                    BorderColor="{AppThemeBinding Dark={StaticResource DarkRadioButtonColor},
                                                  Light={StaticResource LightRadioButtonColor}}"
                    HasShadow="False"
                    HeightRequest="80"
                    HorizontalOptions="Start"
                    VerticalOptions="Start"
                    WidthRequest="80">
                    <Grid Margin="4" WidthRequest="80">
                        <Grid
                            HeightRequest="20"
                            HorizontalOptions="End"
                            VerticalOptions="Start"
                            WidthRequest="20">
                            <Ellipse
                                Fill="White"
                                HeightRequest="18"
                                HorizontalOptions="Center"
                                Stroke="#2E2545"
                                StrokeThickness="1"
                                VerticalOptions="Center"
                                WidthRequest="18" />
                            <Ellipse
                                x:Name="Check"
                                BackgroundColor="Transparent"
                                Fill="#df6e57"
                                HeightRequest="10"
                                HorizontalOptions="Center"
                                Stroke="#df6e57"
                                StrokeThickness="0"
                                VerticalOptions="Center"
                                WidthRequest="10" />
                        </Grid>
                        <!-- This enables us to put in dynamic content -->
                        <ContentPresenter />
                    </Grid>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroupList>
                            <VisualStateGroup x:Name="CheckedStates">
                                <VisualState x:Name="Checked">
                                    <VisualState.Setters>
                                        <Setter Property="BorderColor" Value="#df6e57" />
                                        <Setter TargetName="Check" Property="Opacity" Value="1" />
                                    </VisualState.Setters>
                                </VisualState>
                                <VisualState x:Name="Unchecked">
                                    <VisualState.Setters>
                                        <Setter Property="BorderColor" Value="#F3F2F1" />
                                        <Setter TargetName="Check" Property="Opacity" Value="0" />
                                    </VisualState.Setters>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateGroupList>
                    </VisualStateManager.VisualStateGroups>
                </Frame>
            </ControlTemplate>
        </ResourceDictionary>
    </ContentPage.Resources>

We can now apply this template to each RadioButton. It will continue to use our text label content but apply the control template that we just setup.

<Grid ColumnDefinitions="*,*,*" ColumnSpacing="10">
    <RadioButton ControlTemplate="{StaticResource ThemeRadioTemplate}" Content="Default" IsChecked="True" />
    <RadioButton ControlTemplate="{StaticResource ThemeRadioTemplate}" Grid.Column="1" Content="Light" />
    <RadioButton ControlTemplate="{StaticResource ThemeRadioTemplate}" Grid.Column="2" Content="Dark" />
</Grid>

We aren’t done though as we can now leverage the ContentPresenter and set the Content 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.

<RadioButton.Content>
    <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
        <Image Scale="0.75" Source="{FontImage FontFamily=FA, Glyph={x:Static helpers:FAIcons.UserCog}, Color=#323130}" />
        <Label FontSize="Small" Text="System" TextColor="#323130" />
    </StackLayout>
</RadioButton.Content>

The full XAML for all three RadioButton controls would look a bit like this:

<RadioButton ControlTemplate="{StaticResource ThemeRadioTemplate}" IsChecked="True">
    <RadioButton.Content>
        <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
            <Image Scale="0.75" Source="{FontImage FontFamily=FA, Glyph={x:Static helpers:FAIcons.UserCog}, Color=#323130}" />
            <Label FontSize="Small" Text="System" TextColor="#323130" />
        </StackLayout>
    </RadioButton.Content>
</RadioButton>
<RadioButton ControlTemplate="{StaticResource ThemeRadioTemplate}" Grid.Column="1">
    <RadioButton.Content>
        <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
            <Image Scale="0.75" Source="{FontImage FontFamily=FA, Glyph={x:Static helpers:FAIcons.Sun}, Color=#323130}" />
            <Label FontSize="Small" Text="Light" TextColor="#323130" />
        </StackLayout>
    </RadioButton.Content>
</RadioButton>
<RadioButton ControlTemplate="{StaticResource ThemeRadioTemplate}" Grid.Column="2">
    <RadioButton.Content>
        <StackLayout HorizontalOptions="Center" VerticalOptions="Center">
            <Image Scale="0.75" Source="{FontImage FontFamily=FA, Glyph={x:Static helpers:FAIcons.Moon}, Color=#323130}" />
            <Label FontSize="Small" Text="Dark" TextColor="#323130" />
        </StackLayout>
    </RadioButton.Content>
</RadioButton>

This will result in great cross-platform custom RadioButton!

Learn More

Checkout the full documentation for RadioButton and also control templating for more insight on how to implement this in your app.

You can also browse the source code of LosGatos on GitHub, which is a delightful sample from David Ortinau that uses this technique.

James Montemagno

Principal Lead Program Manager, .NET Community

Follow


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK