我使用此uri https://github.com/AlejandroRuiz/FloatingTextEntry
的自定义渲染器创建了一个带有浮动标签的自定义 条目 字段我需要在按钮点击上更改条目下划线颜色和占位符颜色。
自定义输入代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using Xamarin.Forms;
namespace BloodTrace.CustomControls
{
public class XfxEntry : Entry
{
public static readonly BindableProperty ErrorTextProperty = BindableProperty.Create(nameof(ErrorText),
typeof(string),
typeof(XfxEntry),
default(string), propertyChanged: OnErrorTextChangedInternal);
public static readonly BindableProperty FloatingHintEnabledProperty = BindableProperty.Create(nameof(FloatingHintEnabled),
typeof(bool),
typeof(XfxEntry),
true);
public static readonly BindableProperty ActivePlaceholderColorProperty = BindableProperty.Create(nameof(ActivePlaceholderColor),
typeof(Color),
typeof(XfxEntry),
Color.Accent);
/// <summary>
/// ActivePlaceholderColor summary. This is a bindable property.
/// </summary>
public Color ActivePlaceholderColor
{
get { return (Color)GetValue(ActivePlaceholderColorProperty); }
set { SetValue(ActivePlaceholderColorProperty, value); }
}
public Color ErrorPlaceholderColor
{
get { return (Color)GetValue(ErrorPlaceholderColorProperty); }
set { SetValue(ErrorPlaceholderColorProperty, value); }
}
public static readonly BindableProperty ErrorPlaceholderColorProperty = BindableProperty.Create(nameof(ErrorPlaceholderColor),
typeof(Color),
typeof(XfxEntry),
Color.Green);
/// <summary>
/// <c>true</c> to float the hint into a label, otherwise <c>false</c>. This is a bindable property.
/// </summary>
public bool FloatingHintEnabled
{
get { return (bool)GetValue(FloatingHintEnabledProperty); }
set { SetValue(FloatingHintEnabledProperty, value); }
}
/// <summary>
/// Gets or Sets whether or not the Error Style is 'Underline' or 'None'
/// </summary>
public ErrorDisplay ErrorDisplay { get; set; } = ErrorDisplay.None;
public bool IsErrorPlaceholderColorChange { get; set; } = false;
/// <summary>
/// Error text for the entry. An empty string removes the error. This is a bindable property.
/// </summary>
public string ErrorText
{
get { return (string)GetValue(ErrorTextProperty); }
set { SetValue(ErrorTextProperty, value); }
}
/// <summary>
/// Raised when the value of the error text changes
/// </summary>
public event EventHandler<TextChangedEventArgs> ErrorTextChanged;
private static void OnErrorTextChangedInternal(BindableObject bindable, object oldvalue, object newvalue)
{
var materialEntry = (XfxEntry)bindable;
materialEntry.OnErrorTextChanged(bindable, oldvalue, newvalue);
materialEntry.ErrorTextChanged?.Invoke(materialEntry, new TextChangedEventArgs((string)oldvalue, (string)newvalue));
}
protected virtual void OnErrorTextChanged(BindableObject bindable, object oldvalue, object newvalue) { }
}
public enum ErrorDisplay
{
Underline,
None
}
}
Android Renderer:-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using BloodTrace;
using BloodTrace.Droid.Renderer;
using Application = Android.App.Application;
using Color = Xamarin.Forms.Color;
using AColor = Android.Graphics.Color;
using FormsAppCompat = Xamarin.Forms.Platform.Android.AppCompat;
using BloodTrace.CustomControls;
using Android.Support.Design.Widget;
using Android.Text;
using Xamarin.Forms;
using Android.Content.Res;
using Android.Views.InputMethods;
using Java.Lang;
using Android.Support.V7.Widget;
using Android.Util;
using Xamarin.Forms.Platform.Android;
using System.ComponentModel;
using Android.Text.Method;
using Android.Support.V4.View;
using BloodTrace.Droid.Extensions;
using BloodTraceSharedProject.Extensions;
[assembly: ExportRenderer(typeof(XfxEntry), typeof(XfxEntryRendererDroid))]
namespace BloodTrace.Droid.Renderer
{
public class XfxEntryRendererDroid : FormsAppCompat.ViewRenderer<XfxEntry, TextInputLayout>,
ITextWatcher,
TextView.IOnEditorActionListener
{
private bool _hasFocus;
private ColorStateList _defaultTextColor;
public XfxEntryRendererDroid(Context context) : base(context)
{
AutoPackage = false;
}
protected EditText EditText => Control.EditText;
public bool OnEditorAction(TextView v, ImeAction actionId, KeyEvent e)
{
if ((actionId == ImeAction.Done) || ((actionId == ImeAction.ImeNull) && (e.KeyCode == Keycode.Enter)))
{
Control.ClearFocus();
HideKeyboard();
((IEntryController)Element).SendCompleted();
}
return true;
}
public virtual void AfterTextChanged(IEditable s)
{
}
public virtual void BeforeTextChanged(ICharSequence s, int start, int count, int after)
{
}
public virtual void OnTextChanged(ICharSequence s, int start, int before, int count)
{
if (string.IsNullOrWhiteSpace(Element.Text) && (s.Length() == 0)) return;
((IElementController)Element).SetValueFromRenderer(Entry.TextProperty, s.ToString());
}
protected override TextInputLayout CreateNativeControl()
{
var textInputLayout = new TextInputLayout(Context);
var editText = new AppCompatEditText(Context)
{
SupportBackgroundTintList = ColorStateList.ValueOf(GetPlaceholderColor())
};
editText.SetTextSize(ComplexUnitType.Sp, (float)Element.FontSize);
textInputLayout.AddView(editText);
return textInputLayout;
}
protected override void OnElementChanged(ElementChangedEventArgs<XfxEntry> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
if (Control != null)
EditText.FocusChange -= ControlOnFocusChange;
if (e.NewElement != null)
{
var ctrl = CreateNativeControl();
SetNativeControl(ctrl);
if (!string.IsNullOrWhiteSpace(Element.AutomationId))
EditText.ContentDescription = Element.AutomationId;
_defaultTextColor = EditText.TextColors;
Focusable = true;
EditText.ShowSoftInputOnFocus = true;
// Subscribe
EditText.FocusChange += ControlOnFocusChange;
EditText.AddTextChangedListener(this);
EditText.SetOnEditorActionListener(this);
EditText.ImeOptions = ImeAction.Done;
SetText();
SetHintText();
SetErrorText();
SetFontAttributesSizeAndFamily();
SetInputType();
SetTextColor();
SetHorizontalTextAlignment();
SetFloatingHintEnabled();
SetIsEnabled();
SetErrorDisplay();
SetLabelAndUnderlineColor();
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Entry.PlaceholderProperty.PropertyName)
SetHintText();
else if (e.PropertyName == XfxEntry.ErrorTextProperty.PropertyName)
SetErrorText();
else if (e.PropertyName == Entry.IsPasswordProperty.PropertyName ||
e.PropertyName == InputView.KeyboardProperty.PropertyName)
SetInputType();
else if (e.PropertyName == Entry.TextProperty.PropertyName)
SetText();
else if (e.PropertyName == Entry.HorizontalTextAlignmentProperty.PropertyName)
SetHorizontalTextAlignment();
else if (e.PropertyName == XfxEntry.FloatingHintEnabledProperty.PropertyName)
SetFloatingHintEnabled();
else if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
SetIsEnabled();
else if ((e.PropertyName == Entry.FontAttributesProperty.PropertyName) ||
(e.PropertyName == Entry.FontFamilyProperty.PropertyName) ||
(e.PropertyName == Entry.FontSizeProperty.PropertyName))
SetFontAttributesSizeAndFamily();
else if (e.PropertyName == XfxEntry.ActivePlaceholderColorProperty.PropertyName ||
e.PropertyName == Entry.PlaceholderColorProperty.PropertyName)
SetLabelAndUnderlineColor();
else if (e.PropertyName == Entry.TextColorProperty.PropertyName)
SetTextColor();
}
private void ControlOnFocusChange(object sender, FocusChangeEventArgs args)
{
_hasFocus = args.HasFocus;
if (_hasFocus)
{
var manager = (InputMethodManager)Application.Context.GetSystemService(Context.InputMethodService);
EditText.PostDelayed(() =>
{
EditText.RequestFocus();
manager.ShowSoftInput(EditText, 0);
},
100);
}
var isFocusedPropertyKey = Element.GetInternalField<BindablePropertyKey>("IsFocusedPropertyKey");
((IElementController)Element).SetValueFromRenderer(isFocusedPropertyKey, _hasFocus);
//This will change floating label entry SetUnderlineColor >>>> SetUnderlineColor color basedon focus or non focus
SetUnderlineColor(_hasFocus ? GetActivePlaceholderColor() : GetPlaceholderColor());
}
protected AColor GetPlaceholderColor() => Element.PlaceholderColor.ToAndroid(Color.FromHex("#80000000"));
private AColor GetActivePlaceholderColor() => Element.ActivePlaceholderColor.ToAndroid(global::Android.Resource.Attribute.ColorAccent, Context);
protected virtual void SetLabelAndUnderlineColor()
{
var defaultColor = GetPlaceholderColor();
var activeColor = GetActivePlaceholderColor();
SetHintLabelDefaultColor(defaultColor);
SetHintLabelActiveColor(activeColor);
SetUnderlineColor(_hasFocus ? activeColor : defaultColor);
}
//This will change entry under line color
private void SetUnderlineColor(AColor color)
{
var element = (ITintableBackgroundView)EditText;
element.SupportBackgroundTintList = ColorStateList.ValueOf(color);
}
private void SetHintLabelActiveColor(AColor color)
{
var hintText = Control.Class.GetDeclaredField("mFocusedTextColor");
hintText.Accessible = true;
hintText.Set(Control, new ColorStateList(new int[][] { new[] { 0 } }, new int[] { color }));
}
private void SetHintLabelDefaultColor(AColor color)
{
var hint = Control.Class.GetDeclaredField("mDefaultTextColor");
hint.Accessible = true;
hint.Set(Control, new ColorStateList(new int[][] { new[] { 0 } }, new int[] { color }));
}
private void SetText()
{
if (EditText.Text != Element.Text)
{
EditText.Text = Element.Text;
if (EditText.IsFocused)
EditText.SetSelection(EditText.Text.Length);
}
}
private void SetHintText()
{
Control.Hint = Element.Placeholder;
}
private void SetTextColor()
{
if (Element.TextColor == Color.Default)
{
EditText.SetTextColor(_defaultTextColor);
}
else
{
EditText.SetTextColor(Element.TextColor.ToAndroid());
}
}
private void SetHorizontalTextAlignment()
{
switch (Element.HorizontalTextAlignment)
{
case Xamarin.Forms.TextAlignment.Center:
EditText.Gravity = GravityFlags.CenterHorizontal;
break;
case Xamarin.Forms.TextAlignment.End:
EditText.Gravity = GravityFlags.Right;
break;
default:
EditText.Gravity = GravityFlags.Left;
break;
}
}
public void SetFloatingHintEnabled()
{
Control.HintEnabled = Element.FloatingHintEnabled;
Control.HintAnimationEnabled = Element.FloatingHintEnabled;
SetFontAttributesSizeAndFamily();
}
public void SetErrorDisplay()
{
switch (Element.ErrorDisplay)
{
case ErrorDisplay.None:
Control.ErrorEnabled = false;
break;
case ErrorDisplay.Underline:
Control.ErrorEnabled = true;
break;
}
}
protected void HideKeyboard()
{
var manager = (InputMethodManager)Application.Context.GetSystemService(Context.InputMethodService);
manager.HideSoftInputFromWindow(EditText.WindowToken, 0);
}
//here we can set entry floating label >>> input text size
private void SetFontAttributesSizeAndFamily()
{
EditText.Typeface = Control.Typeface = Element.ToTypeface();
EditText.SetTextSize(ComplexUnitType.Sp, (float)Element.FontSize);
//var a = (float)Element.FontSize; //18
}
private void SetErrorText()
{
Control.Error = !string.IsNullOrEmpty(Element.ErrorText) ? Element.ErrorText : null;
}
private void SetIsEnabled()
{
EditText.Enabled = Element.IsEnabled;
}
private void SetInputType()
{
EditText.InputType = Element.Keyboard.ToInputType();
if (Element.IsPassword && (EditText.InputType & InputTypes.ClassText) == InputTypes.ClassText)
{
EditText.TransformationMethod = new PasswordTransformationMethod();
EditText.InputType = EditText.InputType | InputTypes.TextVariationPassword;
}
if (Element.IsPassword && (EditText.InputType & InputTypes.ClassNumber) == InputTypes.ClassNumber)
{
EditText.TransformationMethod = new PasswordTransformationMethod();
EditText.InputType = EditText.InputType | InputTypes.NumberVariationPassword;
}
}
}
}
XML:-
<xfx:XfxEntry x:Name="EntPassword" Placeholder="Password" IsPassword="True" Focused="EntPassword_Focused"></xfx:XfxEntry>
<Button Text="Sign Up" BackgroundColor="#C62729" TextColor="White" x:Name="BtnSignUp" Clicked="BtnSignUp_Clicked" ></Button>
请帮助。
预先感谢