Michael Lant

Software Archictecture, Development, Agile Methods and the Intersection of People Process and Technology

Buttons, OnPlatform, Software Development, Xamarin, Xamarin Forms, XAML

How To Create Round Buttons in Xamarin Forms

Background

Xamarin Forms is an immensely capable cross-platform development platform for delivering native-code solutions for iOS, Android and UWP. As powerful and complete as it is, there are a few areas where it falls a bit short. One such area is the completeness of the “out of the box” suite of controls. One of the reasons for this apparent deficiency is that the people creating Xamarin work hard to ensure that the controls that they produce for use by developers provide a proper cross-platform experience. This is not simply an issue of rendering or of implementing the correct behaviours of the components; some components exist on one platform, but not on another. To provide a control that does not exist one of the platforms would require creating a control for the target platform where none exists. One such control is the round buttons containing an icon that are often found in Android apps. There is no equivalent on iOS and in fact, Apple explicitly discourages the use of round buttons: https://developer.apple.com/design/human-interface-guidelines/macos/buttons/round-buttons/  

Apple says “No“ to round buttons, but you as the designer may want round buttons for specific tasks. Further, the Google Material Design language https://material.io/ is increasingly finding its way into iOS apps; so much so, that Google has developed a suite of components for iOS developers to use so that their iOS apps can embody the Material Design language – even round buttons https://material.io/develop/ios/components/buttons/

The Paradox for the people at Xamarin, in their efforts to provide cross-platform support for iOS, Android and UWP is what is to be done about a UI Control that exists on one platform and not another, especially when the design language for that platform specifically says that you should not do that? Xamarin has done a brilliant job of striking a solid compromise that works well in most cases. Where a component is missing from one of the platforms, Xamarin typically does not introduce that component to the other platforms where it would be idiomatically inconsistent. There are, however, numerous open source and commercial options available that allow you to address most, if not all of these situations. Or, you can create your own solutions. This article is about how you can easily create your own round buttons with a few simple lines of XAML, no code and without introducing a new component or Nuget package into the mix. It’s surprisingly simple to do. If that’s not of interest to you, then you can install this plugin: https://github.com/wilsonvargas/ButtonCirclePlugin I have not used it, but it appears to be pretty solid and very full-featured.

The Solution

Buttons

The solution to the lack of a round button in Xamarin is a pretty simple one. On all three of the supported Xamarin Forms platforms (iOS, Android, UWP), the Button and ImageButton components allow you to set the corner radius of the button. If you set each of the height and the width of the button to exactly twice that of the radius of the corners, you will end up with a round button. It really is that simple.

<Button x:Name="Button_Round"
    WidthRequest="40"
    HeightRequest="40"
    CornerRadius="20"
    BorderWidth="2"
    BorderColor="Gray"
    Text="+"/>

ImageButton

What about ImageButtons?

The good news is that they work in exactly the same way.

<ImageButton x:Name="ImageButton_Round"
    WidthRequest="40"
    HeightRequest="40"
    CornerRadius="20"
    Source="icon.png"/>

Customizing an ImageButton for Each Platform

ImageButtons are rendered on each platform in the fashion that is appropriate for that platform. That may or may not be what you want for our final result. This too, is pretty easy to address. The following code uses the <OnPlatform… markup to provide custom rendering based on each platform. I am not claiming that any of these examples are ideal, this is just to point you in the right direction should you want to make such platform-specific customizations. Of course you can, and likely should create proper XAML Styles for such things, but this gives you some of the building blocks to do that for the specific Styles that you want to use..

For the images used in this following examples, I am using that are part of the defalut Xamarin Forms project for the iOS and UWP examples. For the Android example, I added an image to the Android project in the /drawables folder and I am referencing that image. In an upcoming post, I will show you how to use Fonts instead of actual images to create icons for use in your application.

Round Buttons – Xamarin Forms Android
Round Buttons – Xamarin Forms iOS
Round Buttions – Xamarin Forms UWP
<ContentPage.Resources>
    <ResourceDictionary>

        <OnPlatform x:Key="Padding_For_ImageButton" x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0,0,0,0"/>
            <On Platform="Android" Value="0,0,0,0"/>
            <On Platform="UWP" Value="2,2,2,2"/>
        </OnPlatform>

        <OnPlatform x:Key="BorderWidth_For_Button" x:TypeArguments="x:Double">
            <On Platform="iOS" Value="2"/>
            <On Platform="Android" Value="0"/>
            <On Platform="UWP" Value="0"/>
        </OnPlatform>

        <OnPlatform x:Key="ImageSource_For_Button" x:TypeArguments="FileImageSource">
            <On Platform="iOS" Value="AppIcon"/>
            <On Platform="Android" Value="icon.png"/>
            <On Platform="UWP" Value="../../Assets/Square44x44Logo.altform-unplated_targetsize-256.png"/>
        </OnPlatform>

        <OnPlatform x:Key="ImageBackgroundColor_For_Button" x:TypeArguments="Color">
            <On Platform="iOS" Value="White"/>
            <On Platform="Android" Value="#FF3598DB"/>
            <On Platform="UWP" Value="#FF3598DB"/>
        </OnPlatform>

        <OnPlatform x:Key="ImageBorderColor_For_Button" x:TypeArguments="Color">
            <On Platform="iOS" Value="Gray"/>
            <On Platform="Android" Value="#FF3598DB"/>
            <On Platform="UWP" Value="#FF3598DB"/>
        </OnPlatform>

    </ResourceDictionary>
</ContentPage.Resources>

<StackLayout>
     <ImageButton x:Name="ImageButton_Round"
        WidthRequest="40"
        HeightRequest="40"
        CornerRadius="20"
        Margin="8"
        BorderWidth="{StaticResource BorderWidth_For_Button}"
        Padding="{StaticResource Padding_For_ImageButton}"
        BackgroundColor="{StaticResource ImageBackgroundColor_For_Button}"
        Source="{StaticResource ImageSource_For_Button}"            
        BorderColor="{StaticResource ImageBorderColor_For_Button}"
        HorizontalOptions="Center"
        VerticalOptions="Start"/>
</StackLayout>

Here is the code for the entire page

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:d="http://xamarin.com/schemas/2014/forms/design"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    x:Class="RoundButtons.MainPage">

<ContentPage.Resources>
    <ResourceDictionary>

        <OnPlatform x:Key="Padding_For_ImageButton" x:TypeArguments="Thickness">
            <On Platform="iOS" Value="0,0,0,0"/>
            <On Platform="Android" Value="0,0,0,0"/>
            <On Platform="UWP" Value="2,2,2,2"/>
        </OnPlatform>

        <OnPlatform x:Key="BorderWidth_For_Button" x:TypeArguments="x:Double">
            <On Platform="iOS" Value="2"/>
            <On Platform="Android" Value="0"/>
            <On Platform="UWP" Value="0"/>
        </OnPlatform>

        <OnPlatform x:Key="ImageSource_For_Button" x:TypeArguments="FileImageSource">
            <On Platform="iOS" Value="AppIcon"/>
            <On Platform="Android" Value="icon.png"/>
            <On Platform="UWP" Value="../../Assets/Square44x44Logo.altform-unplated_targetsize-256.png"/>
        </OnPlatform>

        <OnPlatform x:Key="ImageBackgroundColor_For_Button" x:TypeArguments="Color">
            <On Platform="iOS" Value="White"/>
            <On Platform="Android" Value="#FF3598DB"/>
            <On Platform="UWP" Value="#FF3598DB"/>
        </OnPlatform>

        <OnPlatform x:Key="ImageBorderColor_For_Button" x:TypeArguments="Color">
            <On Platform="iOS" Value="Gray"/>
            <On Platform="Android" Value="#FF3598DB"/>
            <On Platform="UWP" Value="#FF3598DB"/>
        </OnPlatform>

    </ResourceDictionary>
</ContentPage.Resources>

<StackLayout>
    <Label 
        Text="Round Buttons in Xamarin" 
        Margin="8,48,8,8"
        HorizontalOptions="CenterAndExpand"
        VerticalOptions="Start" />

    <Button x:Name="Button_Round"
        BorderColor="Gray"
        BorderWidth="2"
        Text="+"
        Margin="8"
        HorizontalOptions="Center"
        VerticalOptions="Start"
        WidthRequest="40"
        HeightRequest="40"
        BackgroundColor="White"
        CornerRadius="20"/>

    <ImageButton x:Name="ImageButton_Round"
        WidthRequest="40"
        HeightRequest="40"
        CornerRadius="20"
        Margin="8"
        BorderWidth="{StaticResource BorderWidth_For_Button}"
        Padding="{StaticResource Padding_For_ImageButton}"
        BackgroundColor="{StaticResource ImageBackgroundColor_For_Button}"
        Source="{StaticResource ImageSource_For_Button}"            
        BorderColor="{StaticResource ImageBorderColor_For_Button}"
        HorizontalOptions="Center"
        VerticalOptions="Start"/>

</StackLayout>

As always, I look forward to your comments.

Michael

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.