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; |
} |
} |
} |
} |