зеркало из https://github.com/DeGsoft/maui-linux.git
296 строки
8.1 KiB
C#
296 строки
8.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using Android.Content;
|
|
using Android.Content.Res;
|
|
using Android.OS;
|
|
using Android.Text;
|
|
using Android.Text.Method;
|
|
using Android.Util;
|
|
using Android.Views;
|
|
using Java.Lang;
|
|
using Android.Widget;
|
|
|
|
namespace Xamarin.Forms.Platform.Android
|
|
{
|
|
public class EditorRenderer : EditorRendererBase<FormsEditText>
|
|
{
|
|
TextColorSwitcher _hintColorSwitcher;
|
|
TextColorSwitcher _textColorSwitcher;
|
|
|
|
public EditorRenderer(Context context) : base(context)
|
|
{
|
|
}
|
|
|
|
[Obsolete("This constructor is obsolete as of version 2.5. Please use EntryRenderer(Context) instead.")]
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public EditorRenderer()
|
|
{
|
|
AutoPackage = false;
|
|
}
|
|
|
|
protected override FormsEditText CreateNativeControl()
|
|
{
|
|
return new FormsEditText(Context);
|
|
}
|
|
|
|
protected override EditText EditText => Control;
|
|
|
|
protected override void UpdatePlaceholderColor()
|
|
{
|
|
_hintColorSwitcher = _hintColorSwitcher ?? new TextColorSwitcher(EditText.HintTextColors, Element.UseLegacyColorManagement());
|
|
_hintColorSwitcher.UpdateTextColor(EditText, Element.PlaceholderColor, EditText.SetHintTextColor);
|
|
}
|
|
|
|
protected override void UpdateTextColor()
|
|
{
|
|
_textColorSwitcher = _textColorSwitcher ?? new TextColorSwitcher(EditText.TextColors, Element.UseLegacyColorManagement());
|
|
_textColorSwitcher.UpdateTextColor(EditText, Element.TextColor);
|
|
}
|
|
}
|
|
|
|
public abstract class EditorRendererBase<TControl> : ViewRenderer<Editor, TControl>, ITextWatcher
|
|
where TControl : global::Android.Views.View
|
|
{
|
|
bool _disposed;
|
|
protected abstract EditText EditText { get; }
|
|
|
|
public EditorRendererBase(Context context) : base(context)
|
|
{
|
|
AutoPackage = false;
|
|
}
|
|
|
|
[Obsolete("This constructor is obsolete as of version 2.5. Please use EditorRenderer(Context) instead.")]
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public EditorRendererBase()
|
|
{
|
|
AutoPackage = false;
|
|
}
|
|
|
|
IEditorController ElementController => Element;
|
|
|
|
void ITextWatcher.AfterTextChanged(IEditable s)
|
|
{
|
|
}
|
|
|
|
void ITextWatcher.BeforeTextChanged(ICharSequence s, int start, int count, int after)
|
|
{
|
|
}
|
|
|
|
void ITextWatcher.OnTextChanged(ICharSequence s, int start, int before, int count)
|
|
{
|
|
if (string.IsNullOrEmpty(Element.Text) && s.Length() == 0)
|
|
return;
|
|
|
|
if (Element.Text != s.ToString())
|
|
((IElementController)Element).SetValueFromRenderer(Editor.TextProperty, s.ToString());
|
|
}
|
|
|
|
protected override void OnFocusChangeRequested(object sender, VisualElement.FocusRequestArgs e)
|
|
{
|
|
if (!e.Focus)
|
|
{
|
|
EditText.HideKeyboard();
|
|
}
|
|
|
|
base.OnFocusChangeRequested(sender, e);
|
|
|
|
if (e.Focus)
|
|
{
|
|
// Post this to the main looper queue so it doesn't happen until the other focus stuff has resolved
|
|
// Otherwise, ShowKeyboard will be called before this control is truly focused, and we will potentially
|
|
// be displaying the wrong keyboard
|
|
EditText?.PostShowKeyboard();
|
|
}
|
|
}
|
|
|
|
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
|
|
{
|
|
base.OnElementChanged(e);
|
|
|
|
var edit = Control;
|
|
if (edit == null)
|
|
{
|
|
edit = CreateNativeControl();
|
|
|
|
SetNativeControl(edit);
|
|
EditText.AddTextChangedListener(this);
|
|
if(EditText is IFormsEditText formsEditText)
|
|
formsEditText.OnKeyboardBackPressed += OnKeyboardBackPressed;
|
|
}
|
|
|
|
EditText.SetSingleLine(false);
|
|
EditText.Gravity = GravityFlags.Top;
|
|
if ((int)Build.VERSION.SdkInt > 16)
|
|
EditText.TextAlignment = global::Android.Views.TextAlignment.ViewStart;
|
|
EditText.SetHorizontallyScrolling(false);
|
|
|
|
UpdateText();
|
|
UpdateInputType();
|
|
UpdateTextColor();
|
|
UpdateFont();
|
|
UpdateMaxLength();
|
|
UpdatePlaceholderColor();
|
|
UpdatePlaceholderText();
|
|
UpdateIsReadOnly();
|
|
}
|
|
|
|
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
if (e.PropertyName == Editor.TextProperty.PropertyName)
|
|
UpdateText();
|
|
else if (e.PropertyName == InputView.KeyboardProperty.PropertyName)
|
|
UpdateInputType();
|
|
else if (e.PropertyName == InputView.IsSpellCheckEnabledProperty.PropertyName)
|
|
UpdateInputType();
|
|
else if (e.PropertyName == Editor.IsTextPredictionEnabledProperty.PropertyName)
|
|
UpdateInputType();
|
|
else if (e.PropertyName == Editor.TextColorProperty.PropertyName)
|
|
UpdateTextColor();
|
|
else if (e.PropertyName == Editor.FontAttributesProperty.PropertyName)
|
|
UpdateFont();
|
|
else if (e.PropertyName == Editor.FontFamilyProperty.PropertyName)
|
|
UpdateFont();
|
|
else if (e.PropertyName == Editor.FontSizeProperty.PropertyName)
|
|
UpdateFont();
|
|
else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
|
|
UpdateMaxLength();
|
|
else if (e.PropertyName == Editor.PlaceholderProperty.PropertyName)
|
|
UpdatePlaceholderText();
|
|
else if (e.PropertyName == Editor.PlaceholderColorProperty.PropertyName)
|
|
UpdatePlaceholderColor();
|
|
else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
|
|
UpdateIsReadOnly();
|
|
|
|
base.OnElementPropertyChanged(sender, e);
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (_disposed)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_disposed = true;
|
|
|
|
if (disposing)
|
|
{
|
|
if (EditText != null && EditText is IFormsEditText formsEditText)
|
|
{
|
|
formsEditText.OnKeyboardBackPressed -= OnKeyboardBackPressed;
|
|
}
|
|
}
|
|
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
protected virtual NumberKeyListener GetDigitsKeyListener(InputTypes inputTypes)
|
|
{
|
|
// Override this in a custom renderer to use a different NumberKeyListener
|
|
// or to filter out input types you don't want to allow
|
|
// (e.g., inputTypes &= ~InputTypes.NumberFlagSigned to disallow the sign)
|
|
return LocalizedDigitsKeyListener.Create(inputTypes);
|
|
}
|
|
|
|
internal override void OnNativeFocusChanged(bool hasFocus)
|
|
{
|
|
if (Element.IsFocused && !hasFocus) // Editor has requested an unfocus, fire completed event
|
|
ElementController.SendCompleted();
|
|
}
|
|
|
|
protected virtual void UpdateFont()
|
|
{
|
|
EditText.Typeface = Element.ToTypeface();
|
|
EditText.SetTextSize(ComplexUnitType.Sp, (float)Element.FontSize);
|
|
}
|
|
|
|
void UpdateInputType()
|
|
{
|
|
Editor model = Element;
|
|
var edit = EditText;
|
|
var keyboard = model.Keyboard;
|
|
|
|
edit.InputType = keyboard.ToInputType() | InputTypes.TextFlagMultiLine;
|
|
if (!(keyboard is Internals.CustomKeyboard))
|
|
{
|
|
if (model.IsSet(InputView.IsSpellCheckEnabledProperty))
|
|
{
|
|
if (!model.IsSpellCheckEnabled)
|
|
edit.InputType = edit.InputType | InputTypes.TextFlagNoSuggestions;
|
|
}
|
|
if (model.IsSet(Editor.IsTextPredictionEnabledProperty))
|
|
{
|
|
if (!model.IsTextPredictionEnabled)
|
|
edit.InputType = edit.InputType | InputTypes.TextFlagNoSuggestions;
|
|
}
|
|
}
|
|
|
|
if (keyboard == Keyboard.Numeric)
|
|
{
|
|
edit.KeyListener = GetDigitsKeyListener(edit.InputType);
|
|
}
|
|
}
|
|
|
|
void UpdateText()
|
|
{
|
|
string newText = Element.Text ?? "";
|
|
|
|
if (EditText.Text == newText)
|
|
return;
|
|
|
|
EditText.Text = newText;
|
|
EditText.SetSelection(newText.Length);
|
|
}
|
|
|
|
abstract protected void UpdateTextColor();
|
|
|
|
protected virtual void UpdatePlaceholderText()
|
|
{
|
|
if (EditText.Hint == Element.Placeholder)
|
|
return;
|
|
|
|
EditText.Hint = Element.Placeholder;
|
|
}
|
|
|
|
abstract protected void UpdatePlaceholderColor();
|
|
|
|
void OnKeyboardBackPressed(object sender, EventArgs eventArgs)
|
|
{
|
|
ElementController?.SendCompleted();
|
|
EditText?.ClearFocus();
|
|
}
|
|
|
|
void UpdateMaxLength()
|
|
{
|
|
var currentFilters = new List<IInputFilter>(EditText?.GetFilters() ?? new IInputFilter[0]);
|
|
|
|
for (var i = 0; i < currentFilters.Count; i++)
|
|
{
|
|
if (currentFilters[i] is InputFilterLengthFilter)
|
|
{
|
|
currentFilters.RemoveAt(i);
|
|
break;
|
|
}
|
|
}
|
|
|
|
currentFilters.Add(new InputFilterLengthFilter(Element.MaxLength));
|
|
|
|
EditText?.SetFilters(currentFilters.ToArray());
|
|
|
|
var currentControlText = EditText?.Text;
|
|
|
|
if (currentControlText.Length > Element.MaxLength)
|
|
EditText.Text = currentControlText.Substring(0, Element.MaxLength);
|
|
}
|
|
|
|
void UpdateIsReadOnly()
|
|
{
|
|
bool isReadOnly = !Element.IsReadOnly;
|
|
|
|
EditText.FocusableInTouchMode = isReadOnly;
|
|
EditText.Focusable = isReadOnly;
|
|
EditText.SetCursorVisible(isReadOnly);
|
|
}
|
|
}
|
|
} |