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 BorderlessEditor
. 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 BorderlessEditor
will be the foundation for future controls.
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.Editor
followed by a custom renderer class for iOS, Android, and UWP that kills the border.
BorderlessEditor.cs
namespace SuaveControls.MaterialForms { public class BorderlessEditor : Editor { } }
Nothing special here since we are using the default behavior of the Editor
.
Android
Now let’s create an Android custom renderer.
BorderlessEditorRenderer.cs – Android
[assembly: ExportRenderer(typeof(BorderlessEditor), typeof(BorderlessEditorRenderer))] namespace SuaveControls.MaterialForms.Android.Renderers { public class BorderlessEditorRenderer : EditorRenderer { public static void Init() { } protected override void OnElementChanged(ElementChangedEventArgs<Editor> 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 Editor
.
iOS
Follow with an iOS renderer.
BorderlessEditorRenderer.cs – iOS
[assembly: ExportRenderer(typeof(BorderlessEditor), typeof(BorderlessEditorRenderer))] namespace SuaveControls.MaterialForms.iOS.Renderers { public class BorderlessEditorRenderer : EditorRenderer { public static void Init() { } protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); Control.Layer.BorderWidth = 0; } } }
All we do here is set the BorderWidth
to 0.
UWP
Lastly a renderer for UWP
BorderlessEditorRenderer.cs – UWP
[assembly: ExportRenderer(typeof(BorderlessEditor), typeof(BorderlessEditorRenderer))] namespace SuaveControls.MaterialForms.UWP.Renderers { public class BorderlessEditorRenderer : EditorRenderer { public static void Init() { } protected override void OnElementChanged(ElementChangedEventArgs<Editor> 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 BorderlessEditor
Now you can use the BorderlessEditor
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" BackgroundColor="Blue"> <Label Text="Borderless Editor!" Margin="32" HorizontalOptions="Center" HorizontalTextAlignment="Center"/> <suave:BorderlessEditor BackgroundColor="Black" TextColor="White" HeightRequest="300" Margin="32"/> </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.
Many thanks for invaluable information and source code. Just a note on the iOS renderer: it seems to be necessary to check Control (and possibly Control.Layer) for non-null before setting the BorderWidth to zero. Otherwise, there is a risk of an “Object reference not set to an instance of an object” exception.
LikeLike