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. Check those out here:
- Xamarin.Forms Borderless Entry
- Xamarin.Control – Xamarin.Forms MaterialEntry
- Xamarin.Controls – Xamarin.Forms PinView
In this post, we’ll apply some of the same principles to create a BorderlessPicker
. It’s going to use a simple custom renderer, although this could and should be done using an Effect
if being used on its own. However, this BorderlessPicker
will be the foundation for future controls we will create such as the MaterialPicker
that applies Material Design standards to the Xamarin.Forms Picker
control on 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.Picker
followed by a custom renderer class for iOS, Android, and UWP that kills the border.
BorderlessPicker.cs
namespace SuaveControls.MaterialForms { public class BorderlessPicker : Picker { } }
Nothing special here since we are using the default behavior of the Picker
.
Android
Now let’s create an Android custom renderer.
BorderlessPickerRenderer.cs – Android
[assembly: ExportRenderer(typeof(BorderlessPicker), typeof(BorderlessPickerRenderer))] namespace SuaveControls.MaterialForms.Android.Renderers { public class BorderlessPickerRenderer : PickerRenderer { public static void Init() { } protected override void OnElementChanged(ElementChangedEventArgs<Picker> 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 Picker
.
iOS
Follow with an iOS renderer.
BorderlessPickerRenderer.cs – iOS
[assembly: ExportRenderer(typeof(BorderlessPicker), typeof(BorderlessPickerRenderer))] namespace SuaveControls.MaterialForms.iOS.Renderers { public class BorderlessPickerRenderer : PickerRenderer { 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
BorderlessPickerRenderer.cs – UWP
[assembly: ExportRenderer(typeof(BorderlessPicker), typeof(BorderlessPickerRenderer))] namespace SuaveControls.MaterialForms.UWP.Renderers { public class BorderlessPickerRenderer : PickerRenderer { public static void Init() { } protected override void OnElementChanged(ElementChangedEventArgs<Picker> 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 BorderlessPicker
Now you can use the BorderlessPicker
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 Picker!" Margin="32" HorizontalOptions="Center" HorizontalTextAlignment="Center"/> <suave:BorderlessPicker x:Name="PickerDemo" Title="Options"/> </StackLayout> </ScrollView> </ContentPage>
MainPage.xaml.cs
public partial class MainPage : ContentPage { public MainPage() { InitializeComponent(); PickerDemo.ItemsSource = new List<string> { "Option 1", "Option 2", "Option 3", "Option 4" }; } }
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.
hey you are a legend !
LikeLike
Thank you!
LikeLiked by 1 person
thanks buddy.
You save my life. Great article. explained and concise.
Regards
LikeLike
i have implemented the borderlesspicker but now if i open the dialog the items aren’t shown all at the time like in the standard picker. They are like a vertical carousel. how can i change it?
LikeLike
Not sure what you mean by this. All the borderless picker does is remove the border and shadow on the native renderer. This won’t affect anything about the selection process.
LikeLike
i had the same issue like this guy:
https://stackoverflow.com/questions/48622535/how-do-i-style-the-items-list-in-a-xamarin-picker-in-android
All i had to do is let the BorderlessPickerRenderer inherit from
Xamarin.Forms.Platform.Android.AppCompat.PickerRenderer
instead of
Xamarin.Forms.Platform.Android.PickerRenderer
and it was all done.
Maybe you can add this information in your documentation if u want to 🙂
Thanks, Jelitto
LikeLiked by 1 person
The Android PickerRenderer code gives “obsolete” warnings now. See https://stackoverflow.com/questions/47988091/how-to-fix-renderer-warnings-in-android-xamarin-forms
LikeLike