Xamarin.Forms – CustomEntry (BorderWidth, BorderColor and TextPadding)

This project, you can find at: https://github.com/officialdoniald/Xamarin.Forms.CustomControls

We have to create some platforms specific code (custom NavigationPage Renderer), because in the base Xamarin.Forms code, we can’t find this implementation. So first step, we have to create a class in the .NET Standard/PCL project: CustomEntry ( https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls/Entry/CustomEntry.cs ).

using Xamarin.Forms;
namespace XamarinForms.CustomControls.Entry
{
public class CustomEntry : Xamarin.Forms.Entry
{
public static readonly BindableProperty BorderColorProperty =
BindableProperty.Create(nameof(BorderColor), typeof(Color), typeof(CustomEntry));
public static readonly BindableProperty BorderWidthProperty =
BindableProperty.Create(nameof(BorderWidth), typeof(int), typeof(CustomEntry));
public static readonly BindableProperty TextPaddingProperty =
BindableProperty.Create(nameof(TextPadding), typeof(Thickness), typeof(CustomEntry));
/// <summary>
/// Set the Border Color of the Entry.
/// </summary>
public Color BorderColor
{
set { SetValue(BorderColorProperty, value); }
get { return (Color)GetValue(BorderColorProperty); }
}
/// <summary>
/// Set the Border Width of the Entry.
/// </summary>
public int BorderWidth
{
set { SetValue(BorderWidthProperty, value); }
get { return (int)GetValue(BorderWidthProperty); }
}
/// <summary>
/// Set the Text Padding of the Entry.
/// </summary>
public Thickness TextPadding
{
set { SetValue(TextPaddingProperty, value); }
get { return (Thickness)GetValue(TextPaddingProperty); }
}
}
}

Now, we have to implement to the various platforms. Let’s begin with Android: https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls.Android/CustomRenderer/CustomEntryRenderer.cs

using System;
using System.ComponentModel;
using Android.Content;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using XamarinForms.CustomControls.Droid.CustomRenderer;
using XamarinForms.CustomControls.Entry;
[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
namespace XamarinForms.CustomControls.Droid.CustomRenderer
{
#pragma warning disable CS0618
public class CustomEntryRenderer : EntryRenderer
{
private Android.Graphics.Color BorderColor = Android.Graphics.Color.Black;
private int BorderWidth = 1;
private Thickness TextPadding = new Thickness(0);
private CustomEntry CustomEntry;
#endregion
#region Konstruktor
public CustomEntryRenderer() : base() { }
public CustomEntryRenderer(Context context) : base(context) { }
public CustomEntryRenderer(IntPtr a, JniHandleOwnership b) : base() { }
#endregion
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
BorderColor = CustomEntry.BorderColor.ToAndroid();
if (CustomEntry.BorderWidth != 0)
{
BorderWidth = CustomEntry.BorderWidth;
}
TextPadding = CustomEntry.TextPadding;
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Entry> e)
{
base.OnElementChanged(e);
CustomEntry = e.NewElement as CustomEntry;
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
if (CustomEntry != null)
{
ChangeCustomEntryProperties(CustomEntry);
Control.Gravity = GravityFlags.CenterVertical;
int left = Convert.ToInt32(TextPadding.Left);
int right = Convert.ToInt32(TextPadding.Right);
int top = Convert.ToInt32(TextPadding.Top);
int bottom = Convert.ToInt32(TextPadding.Bottom);
Control.SetPadding(left, top, right, bottom);
IntPtr IntPtrtextViewClass = JNIEnv.FindClass(typeof(TextView));
IntPtr mCursorDrawableResProperty = JNIEnv.GetFieldID(IntPtrtextViewClass, “mCursorDrawableRes”, “I”);
JNIEnv.SetField(Control.Handle, mCursorDrawableResProperty, Resource.Drawable.my_cursor);
}
}
private void ChangeCustomEntryProperties(CustomEntry entry)
{
var customEntry = entry;
var nativeEditText = (EditText)Control;
var shape = new ShapeDrawable(new Android.Graphics.Drawables.Shapes.RectShape());
shape.Paint.Color = BorderColor;
shape.Paint.SetStyle(Paint.Style.Stroke);
nativeEditText.Background = shape;
GradientDrawable gd = new GradientDrawable();
gd.SetColor(Android.Graphics.Color.White);
gd.SetStroke(BorderWidth, BorderColor);
nativeEditText.SetBackground(gd);
}
}
#pragma warning restore CS0618
}

This code:

IntPtr IntPtrtextViewClass = JNIEnv.FindClass(typeof(TextView));

IntPtr mCursorDrawableResProperty = JNIEnv.GetFieldID(IntPtrtextViewClass, “mCursorDrawableRes”, “I”);

will change the cursor’s color. If you want to really change the color of the cursor, you have to create in the Resources/Drawable folder a my_cursor.xml file:

<shape xmlns:android=”http://schemas.android.com/apk/res/android” android:shape=”rectangle”>
<solid android:color=”@color/colorCursors”></solid>
<size android:width=”2dp” />
</shape>

@color/colorCursors is a color from the Resources/values/color.xml. If you don’t have this file, just create it:

<?xml version=”1.0″ encoding=”utf-8″?>
<resources>
<color name=”launcher_background”>#FFFFFF</color>
<color name=”colorPrimary”>#3F51B5</color>
<color name=”colorPrimaryDark”>#303F9F</color>
<color name=”colorAccent”>#FF4081</color>
<color name=”colorCursors”>#000000</color>
</resources>

<color name=”colorCursors”>#000000</color> here can you gain the color of the cursor.

If you don’t want to change, just skip this code, comment in it.

Now continue with the iOS site: https://github.com/officialdoniald/Xamarin.Forms.CustomControls/blob/master/XamarinForms.CustomControls/XamarinForms.CustomControls.iOS/CustomRenderer/CustomEntryRenderer.cs

using System.ComponentModel;
using CoreGraphics;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using XamarinForms.CustomControls.Entry;
using XamarinForms.CustomControls.iOS.CustomRenderer;
[assembly: ExportRenderer(typeof(CustomEntry), typeof(CustomEntryRenderer))]
namespace XamarinForms.CustomControls.iOS.CustomRenderer
{
public class CustomEntryRenderer : EntryRenderer
{
#region Properties
private UIColor BorderColor = UIColor.Black;
private int BorderWidth = 1;
private Thickness TextPadding = new Thickness(0);
#endregion
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
var element = ((CustomEntry)sender);
BorderColor = element.BorderColor.ToUIColor();
BorderWidth = element.BorderWidth;
TextPadding = element.TextPadding;
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Entry> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Layer.BorderWidth = BorderWidth;
Control.VerticalAlignment = UIControlContentVerticalAlignment.Center;
Control.LeftView = new UIView(new CGRect(TextPadding.Left, TextPadding.Top, TextPadding.Right, TextPadding.Bottom));
Control.LeftViewMode = UITextFieldViewMode.Always;
Control.TintColor = UIColor.Black;
Control.Layer.BorderColor = BorderColor.CGColor;
//Control.RightView = new UIView(new CGRect(0, 0, 15, 0));
//Control.RightViewMode = UITextFieldViewMode.Always;
//// Use tint color to change the cursor’s color
//Control.TintColor = UIColor.White;
}
}
}
}