using System.ComponentModel; using Android.Content; using Android.Content.Res; using Android.Graphics; using Android.Text; using Android.Views.InputMethods; using Android.Widget; using Bit.Droid.Renderers; using Bit.Droid.Utilities; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; [assembly: ExportRenderer(typeof(Entry), typeof(CustomEntryRenderer))] namespace Bit.Droid.Renderers { public class CustomEntryRenderer : EntryRenderer { public CustomEntryRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs e) { base.OnElementChanged(e); UpdateBorderColor(); if (Control != null && e.NewElement != null) { Control.SetPadding(Control.PaddingLeft, Control.PaddingTop - 10, Control.PaddingRight, Control.PaddingBottom + 20); Control.ImeOptions = Control.ImeOptions | (ImeAction)ImeFlags.NoPersonalizedLearning | (ImeAction)ImeFlags.NoExtractUi; } } // Workaround for bug preventing long-press -> copy/paste on Android 11 // See https://issuetracker.google.com/issues/37095917 protected override void OnAttachedToWindow() { base.OnAttachedToWindow(); Control.Enabled = false; Control.Enabled = true; } // Workaround for failure to disable text prediction on non-password fields // see https://github.com/xamarin/Xamarin.Forms/issues/10857 protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); // Check if changed property is "IsPassword", otherwise ignore if (e.PropertyName == Entry.IsPasswordProperty.PropertyName) { // Check if field type is text, otherwise ignore (numeric passwords, etc.) EditText.InputType = Element.Keyboard.ToInputType(); bool isText = (EditText.InputType & InputTypes.ClassText) == InputTypes.ClassText, isNumber = (EditText.InputType & InputTypes.ClassNumber) == InputTypes.ClassNumber; if (isText || isNumber) { if (Element.IsPassword) { // Element is a password field, set inputType to TextVariationPassword which disables // predictive text by default EditText.InputType = EditText.InputType | (isText ? InputTypes.TextVariationPassword : InputTypes.NumberVariationPassword); } else { // Element is not a password field, set inputType to TextVariationVisiblePassword to // disable predictive text while still displaying the content. EditText.InputType = EditText.InputType | (isText ? InputTypes.TextVariationVisiblePassword : InputTypes.NumberVariationNormal); } // The workaround above forces a reset of the style properties, so we need to re-apply the font. // see https://xamarin.github.io/bugzilla-archives/33/33666/bug.html var typeface = Typeface.CreateFromAsset(Context.Assets, "RobotoMono_Regular.ttf"); if (Control is TextView label) { label.Typeface = typeface; } } } else if (e.PropertyName == Entry.TextColorProperty.PropertyName) { UpdateBorderColor(); } } private void UpdateBorderColor() { if (Control != null) { var states = new[] { new[] { Android.Resource.Attribute.StateFocused }, // focused new[] { -Android.Resource.Attribute.StateFocused }, // unfocused }; var colors = new int[] { ThemeHelpers.PrimaryColor, ThemeHelpers.MutedColor }; Control.BackgroundTintList = new ColorStateList(states, colors); } } } }