diff --git a/global.json b/global.json index 351c7c7e1e..b2b2da7c4f 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "3.1.407" + "version": "3.1.401" }, "msbuild-sdks": { "Microsoft.Build.Traversal": "1.0.43", diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml index a3ba9d0eb3..1ac447ea69 100644 --- a/samples/ControlCatalog/Pages/TextBoxPage.xaml +++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml @@ -13,7 +13,7 @@ - + ("numericWatermark") + .TextInputOptionsQuery += (s, a) => + { + a.ContentType = Avalonia.Input.TextInput.TextInputContentType.Number; + }; } } } diff --git a/src/Android/Avalonia.Android/AndroidInputMethod.cs b/src/Android/Avalonia.Android/AndroidInputMethod.cs index fb6f5a0562..a3e6b6ee88 100644 --- a/src/Android/Avalonia.Android/AndroidInputMethod.cs +++ b/src/Android/Avalonia.Android/AndroidInputMethod.cs @@ -5,6 +5,8 @@ using Android.Content; using Android.Runtime; using Android.Views; using Android.Views.InputMethods; +using Avalonia.Controls.Platform; +using Avalonia.Input; using Avalonia.Input.TextInput; namespace Avalonia.Android @@ -14,6 +16,7 @@ namespace Avalonia.Android { private readonly TView _host; private readonly InputMethodManager _imm; + private IInputElement _inputElement; public AndroidInputMethod(TView host) { @@ -44,7 +47,49 @@ namespace Avalonia.Android public void SetOptions(TextInputOptionsQueryEventArgs options) { - //throw new NotImplementedException(); + if (_inputElement != null) + { + _inputElement.PointerReleased -= RestoreSoftKeyboard; + } + + _inputElement = options.Source as InputElement; + + if (_inputElement == null) + { + _imm.HideSoftInputFromWindow(_host.WindowToken, HideSoftInputFlags.None); + } + + _host.InitEditorInfo((outAttrs) => + { + outAttrs.InputType = options.ContentType switch + { + TextInputContentType.Email => global::Android.Text.InputTypes.TextVariationEmailAddress, + TextInputContentType.Number => global::Android.Text.InputTypes.ClassNumber, + TextInputContentType.Password => global::Android.Text.InputTypes.TextVariationPassword, + TextInputContentType.Phone => global::Android.Text.InputTypes.ClassPhone, + TextInputContentType.Url => global::Android.Text.InputTypes.TextVariationUri, + _ => global::Android.Text.InputTypes.Null + }; + + if (options.AutoCapitalization) + { + outAttrs.InitialCapsMode = global::Android.Text.CapitalizationMode.Sentences; + outAttrs.InputType |= global::Android.Text.InputTypes.TextFlagCapSentences; + } + + if (options.Multiline) + outAttrs.InputType |= global::Android.Text.InputTypes.TextFlagMultiLine; + }); + + Reset(); + _inputElement.PointerReleased += RestoreSoftKeyboard; + RestoreSoftKeyboard(null, null); + } + + private void RestoreSoftKeyboard(object sender, PointerReleasedEventArgs e) + { + //_imm.ToggleSoftInput(ShowFlags.Implicit, HideSoftInputFlags.NotAlways); + _imm.ShowSoftInput(_host, ShowFlags.Implicit); } } } diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs index 3444193140..4267082a4f 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/InvalidationAwareSurfaceView.cs @@ -16,7 +16,6 @@ namespace Avalonia.Android public abstract class InvalidationAwareSurfaceView : SurfaceView, ISurfaceHolderCallback, IPlatformHandle { bool _invalidateQueued; - private ISoftInputElement _softInputElement; readonly object _lock = new object(); private readonly Handler _handler; diff --git a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs index dc9932b38c..a4bc8c4b76 100644 --- a/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs +++ b/src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs @@ -35,7 +35,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform { _view = new ViewImpl(context, this, placeOnTop); _textInputMethod = new AndroidInputMethod(_view); - _keyboardHelper = new AndroidKeyboardEventsHelper(this); + _keyboardHelper = new AndroidKeyboardEventsHelper(this, _textInputMethod); _touchHelper = new AndroidTouchEventsHelper(this, () => InputRoot, GetAvaloniaPointFromEvent); @@ -237,9 +237,5 @@ namespace Avalonia.Android.Platform.SkiaPlatform { throw new NotImplementedException(); } - public void InitEditorInfo(Action init) - { - _view.InitEditorInfo(init); - } } } diff --git a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs index db864c0ee0..d79417a9f1 100644 --- a/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs +++ b/src/Android/Avalonia.Android/Platform/Specific/Helpers/AndroidKeyboardEventsHelper.cs @@ -12,19 +12,22 @@ using Avalonia.Controls; using Avalonia.Controls.Platform; using Avalonia.Input; using Avalonia.Input.Raw; +using Avalonia.Input.TextInput; namespace Avalonia.Android.Platform.Specific.Helpers { - internal class AndroidKeyboardEventsHelper : IDisposable where TView : TopLevelImpl, IAndroidView, ITopLevelImplWithTextInputMethod + internal class AndroidKeyboardEventsHelper : IDisposable where TView : TopLevelImpl, IAndroidView { - private TView _view; + private readonly TView _view; + private readonly ITextInputMethodImpl _textInpuMethod; private IInputElement _lastFocusedElement; public bool HandleEvents { get; set; } - public AndroidKeyboardEventsHelper(TView view) + public AndroidKeyboardEventsHelper(TView view, ITextInputMethodImpl androidTextInput) { - this._view = view; + _view = view; + _textInpuMethod = androidTextInput; HandleEvents = true; } @@ -100,71 +103,6 @@ namespace Avalonia.Android.Platform.Specific.Helpers return rv; } - private bool NeedsKeyboard(IInputElement element) - { - //may be some other elements - return element is ISoftInputElement; - } - - private void TryShowHideKeyboard(ISoftInputElement element, bool value) - { - _view.InitEditorInfo((outAttrs) => - { - outAttrs.InputType = element.InputType switch - { - InputType.Numeric => global::Android.Text.InputTypes.ClassNumber, - InputType.Phone => global::Android.Text.InputTypes.ClassPhone, - _ => global::Android.Text.InputTypes.Null - }; - }); - - var input = _view.View.Context.GetSystemService(Context.InputMethodService).JavaCast(); - - if (value && element != null && element.InputType != InputType.None) - { - _view.View.RequestFocus(); - - if (!ReferenceEquals(_lastFocusedElement, element)) - { - input.RestartInput(_view.View); - } - - input.ToggleSoftInput(ShowFlags.Forced, HideSoftInputFlags.NotAlways); - } - else - { - input.HideSoftInputFromWindow(_view.View.WindowToken, HideSoftInputFlags.None); - } - } - - public void UpdateKeyboardState(IInputElement element) - { - var focusedElement = element as ISoftInputElement; - var lastElement = _lastFocusedElement as ISoftInputElement; - - bool oldValue = lastElement?.InputType > InputType.None; - bool newValue = focusedElement?.InputType > InputType.None; - - if (newValue != oldValue || newValue) - { - if (_lastFocusedElement != null) - _lastFocusedElement.PointerReleased -= RestoreSoftKeyboard; - - TryShowHideKeyboard(focusedElement, newValue); - - if (newValue && focusedElement != null) - element.PointerReleased += RestoreSoftKeyboard; - } - - _lastFocusedElement = element; - } - - private void RestoreSoftKeyboard(object sender, PointerReleasedEventArgs e) - { - if (_lastFocusedElement is ISoftInputElement softInputElement && softInputElement.InputType != InputType.None) - TryShowHideKeyboard(softInputElement, true); - } - public void ActivateAutoShowKeyboard() { var kbDevice = (KeyboardDevice.Instance as INotifyPropertyChanged); @@ -178,7 +116,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers { if (e.PropertyName == nameof(KeyboardDevice.FocusedElement)) { - UpdateKeyboardState(KeyboardDevice.Instance.FocusedElement); + //UpdateKeyboardState(KeyboardDevice.Instance.FocusedElement); } } diff --git a/src/Android/Avalonia.Android/Platform/Specific/IAndroidView.cs b/src/Android/Avalonia.Android/Platform/Specific/IAndroidView.cs index 1f99051fe6..662792a4df 100644 --- a/src/Android/Avalonia.Android/Platform/Specific/IAndroidView.cs +++ b/src/Android/Avalonia.Android/Platform/Specific/IAndroidView.cs @@ -6,7 +6,5 @@ namespace Avalonia.Android.Platform.Specific public interface IAndroidView { View View { get; } - - } } diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 06729fa990..1d75f08a41 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -18,7 +18,7 @@ using Avalonia.Controls.Metadata; namespace Avalonia.Controls { [PseudoClasses(":empty")] - public class TextBox : TemplatedControl, UndoRedoHelper.IUndoRedoHost, ISoftInputElement + public class TextBox : TemplatedControl, UndoRedoHelper.IUndoRedoHost { public static KeyGesture CutGesture { get; } = AvaloniaLocator.Current .GetService()?.Cut.FirstOrDefault(); @@ -130,11 +130,6 @@ namespace Avalonia.Controls nameof(CanPaste), o => o.CanPaste); - public static readonly DirectProperty InputTypeProperty = - AvaloniaProperty.RegisterDirect( - nameof(InputType), - o => o.InputType); - struct UndoRedoState : IEquatable { public string Text { get; } @@ -1248,7 +1243,5 @@ namespace Avalonia.Controls ClearSelection(); } } - - public InputType InputType { get; set; } = InputType.Text; } } diff --git a/src/Avalonia.Input/ISoftInputElement.cs b/src/Avalonia.Input/ISoftInputElement.cs deleted file mode 100644 index ed5e4e59e3..0000000000 --- a/src/Avalonia.Input/ISoftInputElement.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Avalonia.Input -{ - public interface ISoftInputElement - { - InputType InputType { get; } - } -} diff --git a/src/Avalonia.Input/InputType.cs b/src/Avalonia.Input/InputType.cs deleted file mode 100644 index 893f9dcc39..0000000000 --- a/src/Avalonia.Input/InputType.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Avalonia.Input -{ - /// - /// Input type enumeration - /// - public enum InputType - { - /// - /// Do not use input - /// - None, - - /// - /// User full text input - /// - Text, - - /// - /// Use numeric text input - /// - Numeric, - - /// - /// Use phone input - /// - Phone - } -}