committed by
GitHub
11 changed files with 230 additions and 93 deletions
@ -0,0 +1,96 @@ |
|||||
|
using System; |
||||
|
using Android.Content; |
||||
|
using Android.Runtime; |
||||
|
using Android.Views; |
||||
|
using Android.Views.InputMethods; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Input.TextInput; |
||||
|
|
||||
|
namespace Avalonia.Android |
||||
|
{ |
||||
|
class AndroidInputMethod<TView> : ITextInputMethodImpl |
||||
|
where TView: View, IInitEditorInfo |
||||
|
{ |
||||
|
private readonly TView _host; |
||||
|
private readonly InputMethodManager _imm; |
||||
|
private IInputElement _inputElement; |
||||
|
|
||||
|
public AndroidInputMethod(TView host) |
||||
|
{ |
||||
|
if (host.OnCheckIsTextEditor() == false) |
||||
|
throw new InvalidOperationException("Host should return true from OnCheckIsTextEditor()"); |
||||
|
|
||||
|
_host = host; |
||||
|
_imm = host.Context.GetSystemService(Context.InputMethodService).JavaCast<InputMethodManager>(); |
||||
|
|
||||
|
_host.Focusable = true; |
||||
|
_host.FocusableInTouchMode = true; |
||||
|
_host.ViewTreeObserver.AddOnGlobalLayoutListener(new SoftKeyboardListner(_host)); |
||||
|
} |
||||
|
|
||||
|
public void Reset() |
||||
|
{ |
||||
|
_imm.RestartInput(_host); |
||||
|
} |
||||
|
|
||||
|
public void SetActive(bool active) |
||||
|
{ |
||||
|
if (active) |
||||
|
{ |
||||
|
_host.RequestFocus(); |
||||
|
Reset(); |
||||
|
_imm.ShowSoftInput(_host, ShowFlags.Implicit); |
||||
|
} |
||||
|
else |
||||
|
_imm.HideSoftInputFromWindow(_host.WindowToken, HideSoftInputFlags.None); |
||||
|
} |
||||
|
|
||||
|
public void SetCursorRect(Rect rect) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public void SetOptions(TextInputOptionsQueryEventArgs options) |
||||
|
{ |
||||
|
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.ClassText |
||||
|
}; |
||||
|
|
||||
|
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; |
||||
|
}); |
||||
|
|
||||
|
//_inputElement.PointerReleased += RestoreSoftKeyboard;
|
||||
|
} |
||||
|
|
||||
|
private void RestoreSoftKeyboard(object sender, PointerReleasedEventArgs e) |
||||
|
{ |
||||
|
_imm.ShowSoftInput(_host, ShowFlags.Implicit); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
using Android.Views.InputMethods; |
||||
|
|
||||
|
namespace Avalonia.Android |
||||
|
{ |
||||
|
interface IInitEditorInfo |
||||
|
{ |
||||
|
void InitEditorInfo(Action<EditorInfo> init); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
using Android.Content; |
||||
|
using Android.OS; |
||||
|
using Android.Util; |
||||
|
using Android.Views; |
||||
|
using Avalonia.Input; |
||||
|
|
||||
|
namespace Avalonia.Android |
||||
|
{ |
||||
|
class SoftKeyboardListner : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener |
||||
|
{ |
||||
|
private const int DefaultKeyboardHeightDP = 100; |
||||
|
private static readonly int EstimatedKeyboardDP = DefaultKeyboardHeightDP + (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop ? 48 : 0); |
||||
|
|
||||
|
private readonly View _host; |
||||
|
private bool _wasKeyboard; |
||||
|
|
||||
|
public SoftKeyboardListner(View view) |
||||
|
{ |
||||
|
_host = view; |
||||
|
} |
||||
|
|
||||
|
public void OnGlobalLayout() |
||||
|
{ |
||||
|
int estimatedKeyboardHeight = (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, |
||||
|
EstimatedKeyboardDP, _host.Resources.DisplayMetrics); |
||||
|
|
||||
|
var rect = new global::Android.Graphics.Rect(); |
||||
|
_host.GetWindowVisibleDisplayFrame(rect); |
||||
|
|
||||
|
int heightDiff = _host.RootView.Height - (rect.Bottom - rect.Top); |
||||
|
var isKeyboard = heightDiff >= estimatedKeyboardHeight; |
||||
|
|
||||
|
if (_wasKeyboard && !isKeyboard) |
||||
|
KeyboardDevice.Instance.SetFocusedElement(null, NavigationMethod.Unspecified, KeyModifiers.None); |
||||
|
|
||||
|
_wasKeyboard = isKeyboard; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue