Xamarin.Tip – Borderless TimePicker

I previously put out a post on removing the border of a Xamarin.Forms Entry which was then used to create a custom PinView as well as a MaterialEntry that follows the material design standards for text fields. I also added a post just like this one that talks about creating a BorderlessPicker. Check those out here:

In this post, we’ll do exactly what we did with the BorderlessPicker, but apply it to the Xamarin.Forms.TimePicker control to remove the border. This would ideally be done using an Effect, however we will be using this control in a later post to create a MaterialTimePicker to fit the Material Design standards for form inputs, so we will create custom renderers for Android, iOS, and UWP.

You can find this code as part of my library in progress to create Material Design Form controls for Xamarin.Forms – https://github.com/SuavePirate/SuaveControls.MaterialFormControls.

Let’s get started with our custom control by first creating a custom subclass of Xamarin.Forms.TimePicker followed by a custom renderer class for iOS, Android, and UWP that kills the border.

BorderlessTimePicker.cs

namespace SuaveControls.MaterialForms
{
    public class BorderlessTimePicker : TimePicker
    {
    }
}

Nothing special here since we are using the default behavior of the TimePicker.

Android

Now let’s create an Android custom renderer.

BorderlessTimePickerRenderer.cs – Android

[assembly: ExportRenderer(typeof(BorderlessTimePicker), typeof(BorderlessTimePickerRenderer))]
namespace SuaveControls.MaterialForms.Android.Renderers
{
    public class BorderlessTimePickerRenderer : TimePickerRenderer
    {
        public static void Init() { }
        protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
        {
            base.OnElementChanged(e);
            if (e.OldElement == null)
            {
                Control.Background = null;

                var layoutParams = new MarginLayoutParams(Control.LayoutParameters);
                layoutParams.SetMargins(0, 0, 0, 0);
                LayoutParameters = layoutParams;
                Control.LayoutParameters = layoutParams;
                Control.SetPadding(0, 0, 0, 0);
                SetPadding(0, 0, 0, 0);
            }
        }
    }
}

We simple kill the default padding and margins while setting the Background property to null. This Background is what creates the drawable underline for the AppCompat TimePicker.

iOS

Follow with an iOS renderer.

BorderlessTimePickerRenderer.cs – iOS

[assembly: ExportRenderer(typeof(BorderlessTimePicker), typeof(BorderlessTimePickerRenderer))]
namespace SuaveControls.MaterialForms.iOS.Renderers
{
    public class BorderlessTimePickerRenderer : TimePickerRenderer
    {
        public static void Init() { }
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            Control.Layer.BorderWidth = 0;
            Control.BorderStyle = UITextBorderStyle.None;
        }
    }
}

All we do here is set the BorderWidth to 0 and the BorderStyle to UITextBorderStyle.None.

UWP

Lastly a renderer for UWP

BorderlessTimePickerRenderer.cs – UWP


[assembly: ExportRenderer(typeof(BorderlessTimePicker), typeof(BorderlessTimePickerRenderer))]

namespace SuaveControls.MaterialForms.UWP.Renderers
{
    public class BorderlessTimePickerRenderer : TimePickerRenderer
    {
        public static void Init() { }
        protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                Control.BorderThickness = new Windows.UI.Xaml.Thickness(0);
                Control.Margin = new Windows.UI.Xaml.Thickness(0);
                Control.Padding = new Windows.UI.Xaml.Thickness(0);
            }
        }
    }
}

Similar to how we did it on Android, we set both the Margin and Padding to 0 and also set the BorderThickness to a 0’d Thickness.

Using the BorderlessTimePicker

Now you can use the BorderlessTimePicker in your XAML or C# code:

MainPage.xaml

<?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:local="clr-namespace:ExampleMaterialApp"
             xmlns:suave="clr-namespace:SuaveControls.MaterialForms;assembly=SuaveControls.MaterialForms"
             x:Class="ExampleMaterialApp.MainPage">

    <ScrollView>
        <StackLayout Spacing="16" Margin="16">
            <Label Text="Borderless TimePicker!" Margin="32" HorizontalOptions="Center" HorizontalTextAlignment="Center"/>
            <suave:BorderlessTimePicker/>

        </StackLayout>
    </ScrollView>

</ContentPage>

Check out those results on iOS:

If you like what you see, don’t forget to follow me on twitter @Suave_Pirate, check out my GitHub, and subscribe to my blog to learn more mobile developer tips and tricks!

Interested in sponsoring developer content? Message @Suave_Pirate on twitter for details.

5 thoughts on “Xamarin.Tip – Borderless TimePicker”

  1. Hi, Alex very interesting tip. I’m trying to use on VS for Mac and I got this error:
    Error: This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is ../packages/Xamarin.Forms.2.3.4.247/build/portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20/Xamarin.Forms.targets. (SuaveControls.MaterialForms)
    But I have done nothing with the code, I just try to run as it is.
    I did restore the NuGet Package with same results.
    Any advice on this?

    Like

Leave a comment