Radio button personalizado en Xamarin Forms 5

Uno de los controles que ha sufrido bastantes cambios con la llegada de Xamarin.Forms 5 es el RadioButton. Se han incluido nuevas propiedades, que facilitan su personalización. Por ejemplo, BorderColor, CornerRadius, Content, etc… Gracias a la propiedad content, podemos meter una view en el RadioButton, llegando a tener lo que queramos, consiguiendo efectos como el siguiente.

<RadioButton Grid.Column="0"
GroupName="Group1"
CornerRadius="20"
BackgroundColor="LightGray" BorderColor="Black">
<RadioButton.Content>
<StackLayout Orientation="Vertical" Spacing="0" VerticalOptions="Center">
<Image Source="email.png" />
<Label Text="Email" HorizontalTextAlignment="Center" />
</StackLayout>
</RadioButton.Content>
</RadioButton>
No obstante, a mi juicio, el cambio más importante es que ahora hereda de TemplatedView, por lo que podemos realizar el diseño que más nos interese, sin limitarnos a las propiedades que ofrece para cambiar su aspecto. Asimismo, como tiene dos visual states (Checked y Unchecked) podemos usarlos para dar una aspecto diferente al control, en función de si está chequeado o no. De esta manera, el objetivo de este post es conseguir que un RadioButton tenga el aspecto que se muestra a continuación.

El primer objetivo que nos tenemos que marcar, es conseguir aspecto del control, sin tener en cuenta los visual states. Para ello, creamos una plantilla, que contenga un circulo (Elipse con misma ancho que alto), con el fondo gris y el borde negro.
<ControlTemplate x:Key="CustomRadioTemplate">
<Grid>
<Ellipse Fill="LightGray" Stroke="Black" StrokeThickness="2"
HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
<ContentPresenter />
</Grid>
</ControlTemplate>
Tal y como vemos en el código, lo único que tiene la plantilla es un circulo gris con el borde negro y, en su interior, el ContentPresenter, que será sustituido con el Content del RadioButton.
Con la plantilla ya creada, la asignamos al control y tenemos este resultado.

<RadioButton Grid.Column="0"
GroupName="Group1"
ControlTemplate="{StaticResource CustomRadioTemplate}" >
<RadioButton.Content>
<StackLayout Orientation="Vertical" Spacing="0" VerticalOptions="Center">
<Image Source="email.png" />
<Label Text="Email" HorizontalTextAlignment="Center" />
</StackLayout>
</RadioButton.Content>
</RadioButton>
En este punto, el problema que tenemos es que el control siempre tiene el mismo aspecto, esté chequeado o no lo esté. Para solucionarlo, editamos la plantilla y añadimos otro circulo, con el fondo anaranjado y el borde rojo. Y, dependiendo del visual state, se mostrará un circulo u otro, utilizando su propiedad IsVisible.
<ControlTemplate x:Key="CustomRadioTemplate">
<Grid>
<Ellipse x:Name="CheckedCircle"
Fill="LightSalmon" Stroke="Red" StrokeThickness="2"
HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
<Ellipse x:Name="UncheckedCircle"
Fill="LightGray" Stroke="Black" StrokeThickness="2"
HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
<ContentPresenter />
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<VisualStateGroup x:Name="CheckeState">
<VisualState x:Name="Checked">
<VisualState.Setters>
<Setter TargetName="CheckedCircle" Property="IsVisible" Value="True" />
<Setter TargetName="UncheckedCircle" Property="IsVisible" Value="False" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Unchecked">
<VisualState.Setters>
<Setter TargetName="CheckedCircle" Property="IsVisible" Value="False" />
<Setter TargetName="UncheckedCircle" Property="IsVisible" Value="True" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
Con todo esto, ya tendríamos el RadioButton con el aspecto que nos habíamos propuesto inicialmente.
Como siempre, aquí os dejo un enlace al repositorio del proyecto de ejemplo que he creado, para que podáis descargarlo y dar a vuestros RadioButton el aspecto que más os guste https://github.com/jorgediegocrespo/XF5RadioButton