Search code examples
c#xamlxamarinxamarin.formscontroltemplate

Custom RadioButton Frame with text inside


I am trying to create a custom look for RadioButton different from the default one as shown in image below:

enter image description here

Any idea how can I do it?


Solution

  • Starting from Xamarin forms 5.0.0.1539-pre2 version, RadioButton does supports setting any content and using control templates and thus less need for custom renderer, and if we combine this with visual-state-manager we will get a beautiful xaml:

    <ContentPage.Resources>
        <ControlTemplate x:Key="FrameRadioTemplate">
            <Frame Padding="0" BorderColor="#2B79E1" CornerRadius="15" VerticalOptions="Start"
                   HeightRequest="100" WidthRequest="100" HorizontalOptions="Start">
    
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CheckedStates">
                        <VisualState x:Name="Checked">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="#2B79E1"/>
                            </VisualState.Setters>
                        </VisualState>
    
                        <VisualState x:Name="Unchecked">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="#f3f2f1"/>
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
    
                <Grid Margin="4" WidthRequest="100">
                    <ContentPresenter/>
                </Grid>
            </Frame>
        </ControlTemplate>
    </ContentPage.Resources>
    
    <StackLayout HorizontalOptions="Center"  VerticalOptions="Center" Orientation="Horizontal">
        <RadioButton ControlTemplate="{StaticResource FrameRadioTemplate}">
            <RadioButton.Content>
                <Label Text="RadioButton 1" TextColor="Black"/>
            </RadioButton.Content>
        </RadioButton>
    
        <RadioButton ControlTemplate="{StaticResource FrameRadioTemplate}">
            <RadioButton.Content>
                <Label Text="RadioButton 2" TextColor="Black"/>
            </RadioButton.Content>
        </RadioButton>
    </StackLayout>
    

                        enter image description here

    Inspired from David Ortinau sample


    EDIT

    To make the TextColor white of the labels when respective RadioButton is checked you have several options:

    1- Use a value converter with parameter bound to IsCheked. 2- Define style inline. 3- Use Style.Triggers inside the ControlTemplate which is shown below.

    <ContentPage.Resources>
        <ControlTemplate x:Key="FrameRadioTemplate">
            <Frame Padding="5" CornerRadius="15" BorderColor="#2B79E1"
                   HeightRequest="120" WidthRequest="120">
    
                <ContentPresenter>
                    <ContentPresenter.Resources>
                        <Style TargetType="Label">
                            <Setter Property="HorizontalOptions" Value="Center"/>
                            <Setter Property="VerticalOptions" Value="Center"/>
    
                            <Style.Triggers>
                                <DataTrigger TargetType="Label"
                                             Binding="{Binding Path=IsChecked,
                                                               Source={x:RelativeSource AncestorType={x:Type RadioButton}}}"
                                             Value="True">
                                    <Setter Property="TextColor" Value="White"/>
                                    <Setter Property="FontAttributes" Value="Bold"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </ContentPresenter.Resources>
                </ContentPresenter>
    
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="CheckedStates">
                        <VisualState x:Name="Checked">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="#2B79E1"/>
                            </VisualState.Setters>
                        </VisualState>
    
                        <VisualState x:Name="Unchecked">
                            <VisualState.Setters>
                                <Setter Property="BackgroundColor" Value="#f3f2f1"/>
                            </VisualState.Setters>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>
            </Frame>
        </ControlTemplate>
    </ContentPage.Resources>
    
    <ContentPage.Content>
        <StackLayout HorizontalOptions="Center" Orientation="Horizontal" Spacing="30"
                     VerticalOptions="Center">
            <RadioButton ControlTemplate="{StaticResource FrameRadioTemplate}" IsChecked="True">
                <RadioButton.Content>
                    <Label Text="RadioButton 1" TextColor="Black"/>
                </RadioButton.Content>
            </RadioButton>
    
            <RadioButton ControlTemplate="{StaticResource FrameRadioTemplate}">
                <RadioButton.Content>
                    <Label Text="RadioButton 2" TextColor="Black"/>
                </RadioButton.Content>
            </RadioButton>
        </StackLayout>
    </ContentPage.Content>
    

                        enter image description here