I tried to create a Material Design Entry for Xamarin Forms and I have a problem with the hint color and the bottom line.
EDIT with York Shen answer:
Xaml Page
<customControls:CustomEntry
Keyboard="Email"
Placeholder="EMAIL"
Style="{StaticResource EntryAccount}"
Text="{Binding Email}" />
EntryAccount Style
<Style x:Key="EntryAccount" TargetType="customControls:CustomEntry">
<Setter Property="PlaceholderColor" Value="{StaticResource BackgroundColor}" />
<Setter Property="BottomLineColor" Value="{StaticResource BackgroundColor}" />
<Setter Property="TextColor" Value="{StaticResource BackgroundColor}" />
<Setter Property="FontSize" Value="{StaticResource Subtitle1}" />
<Setter Property="FontFamily" Value="{StaticResource Subtitle1Font}" />
</Style>
CustomEntry
public class CustomEntry : Entry
{
public static readonly BindableProperty BottomLineColorProperty =
BindableProperty.Create(nameof(BottomLineColor), typeof(Color), typeof(CustomEntry), Color.Blue);
public Color BottomLineColor
{
get => (Color) GetValue(BottomLineColorProperty);
set => SetValue(BottomLineColorProperty, value);
}
}
CustomEntryRenderer
public class CustomEntryRenderer : Xamarin.Forms.Platform.Android.AppCompat.ViewRenderer<CustomEntry, TextInputLayout>
{
public CustomEntryRenderer(Context context) : base(context)
{
}
protected EditText EditText => Control.EditText;
protected override TextInputLayout CreateNativeControl()
{
var textInputLayout = new TextInputLayout(Context);
var editText = new AppCompatEditText(Context);
editText.SetTextSize(ComplexUnitType.Sp, (float) Element.FontSize);
textInputLayout.AddView(editText);
return textInputLayout;
}
protected override void OnElementChanged(ElementChangedEventArgs<CustomEntry> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var ctrl = CreateNativeControl();
SetNativeControl(ctrl);
var activeColor = Element.BottomLineColor.ToAndroid(global::Android.Resource.Attribute.ColorAccent, Context);
var hintText = Control.Class.GetDeclaredField("mFocusedTextColor");
hintText.Accessible = true;
hintText.Set(Control, new ColorStateList(new int[][] {new[] {0}}, new int[] {activeColor}));
EditText.Enabled = Element.IsEnabled;
Control.Hint = Element.Placeholder;
EditText.SetTextColor(Element.TextColor.ToAndroid());
}
}
}
Element.TextColor & activeColor correctly get the colors that I pass in param.
But this is my results:
Xamarin Forms and Material design, how to change hint color
You could add an AppCompatEditText
to the TextInputLayout
:
protected EditText EditText => Control.EditText;
protected override TextInputLayout CreateNativeControl()
{
var textInputLayout = new TextInputLayout(Context);
var editText = new AppCompatEditText(Context);
editText.SetTextSize(ComplexUnitType.Sp, (float)Element.FontSize);
textInputLayout.AddView(editText);
return textInputLayout;
}
Then set hint text color like this:
var activeColor = Element.ActiveHintTextColor.ToAndroid(global::Android.Resource.Attribute.ColorAccent, Context);
var hintText = Control.Class.GetDeclaredField("mFocusedTextColor");
hintText.Accessible = true;
hintText.Set(Control, new ColorStateList(new int[][] { new[] { 0 } }, new int[] { activeColor }));
public class CustomEntry : Entry
{
public static readonly BindableProperty ActiveHintTextColorProperty = BindableProperty.Create(nameof(ActiveHintTextColor),
typeof(Color),
typeof(CustomEntry),
Color.Accent);
/// <summary>
/// ActiveHintTextColor summary. This is a bindable property.
/// </summary>
public Color ActiveHintTextColor
{
get { return (Color)GetValue(ActiveHintTextColorProperty); }
set { SetValue(ActiveHintTextColorProperty, value); }
}
}
public class CustomEntryRenderer : Xamarin.Forms.Platform.Android.AppCompat.ViewRenderer<CustomEntry, TextInputLayout>
{
public CustomEntryRenderer (Context context) : base(context)
{
}
protected EditText EditText => Control.EditText;
protected override TextInputLayout CreateNativeControl()
{
var textInputLayout = new TextInputLayout(Context);
var editText = new AppCompatEditText(Context);
editText.SetTextSize(ComplexUnitType.Sp, (float)Element.FontSize);
textInputLayout.AddView(editText);
return textInputLayout;
}
protected override void OnElementChanged(ElementChangedEventArgs<XfxEntry> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
var ctrl = CreateNativeControl();
SetNativeControl(ctrl);
var activeColor = Element.ActiveHintTextColor.ToAndroid(global::Android.Resource.Attribute.ColorAccent, Context);
var hintText = Control.Class.GetDeclaredField("mFocusedTextColor");
hintText.Accessible = true;
hintText.Set(Control, new ColorStateList(new int[][] { new[] { 0 } }, new int[] { activeColor }));
EditText.Enabled = Element.IsEnabled;
Control.Hint = Element.Placeholder;
EditText.SetTextColor(Element.TextColor.ToAndroid());
}
}
}
<local:CustomEntry
Placeholder="Enter your name:"
Text="Name"
ActiveHintTextColor="Blue"
PlaceholderColor="Black"
/>
Set the bottom line color:
var element = (ITintableBackgroundView)EditText;
//using AColor = Android.Graphics.Color;
element.SupportBackgroundTintList = ColorStateList.ValueOf(AColor.White);