A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

145 lines
4.5 KiB

using System;
using System.ComponentModel;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Views.InputMethods;
using Avalonia.Android.Platform.Input;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Platform;
namespace Avalonia.Android.Platform.Specific.Helpers
{
public class AndroidKeyboardEventsHelper<TView> : IDisposable where TView :ITopLevelImpl, IAndroidView
{
private TView _view;
private IInputElement _lastFocusedElement;
public bool HandleEvents { get; set; }
public AndroidKeyboardEventsHelper(TView view)
{
this._view = view;
HandleEvents = true;
}
public bool? DispatchKeyEvent(KeyEvent e, out bool callBase)
{
if (!HandleEvents)
{
callBase = true;
return null;
}
return DispatchKeyEventInternal(e, out callBase);
}
private bool? DispatchKeyEventInternal(KeyEvent e, out bool callBase)
{
if (e.Action == KeyEventActions.Multiple)
{
callBase = true;
return null;
}
var rawKeyEvent = new RawKeyEventArgs(
AndroidKeyboardDevice.Instance,
Convert.ToUInt32(e.EventTime),
e.Action == KeyEventActions.Down ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
AndroidKeyboardDevice.ConvertKey(e.KeyCode), GetModifierKeys(e));
_view.Input(rawKeyEvent);
if (e.Action == KeyEventActions.Down && e.UnicodeChar >= 32)
{
var rawTextEvent = new RawTextInputEventArgs(
AndroidKeyboardDevice.Instance,
Convert.ToUInt32(e.EventTime),
Convert.ToChar(e.UnicodeChar).ToString()
);
_view.Input(rawTextEvent);
}
if (e.Action == KeyEventActions.Up)
{
//nothing to do here more call base no need of more events
callBase = true;
return null;
}
callBase = false;
return false;
}
private static RawInputModifiers GetModifierKeys(KeyEvent e)
{
var rv = RawInputModifiers.None;
if (e.IsCtrlPressed) rv |= RawInputModifiers.Control;
if (e.IsShiftPressed) rv |= RawInputModifiers.Shift;
return rv;
}
private bool NeedsKeyboard(IInputElement element)
{
//may be some other elements
return element is TextBox;
}
private void TryShowHideKeyboard(IInputElement element, bool value)
{
var input = _view.View.Context.GetSystemService(Context.InputMethodService).JavaCast<InputMethodManager>();
if (value)
{
//show keyboard
//may be in the future different keyboards support e.g. normal, only digits etc.
//Android.Text.InputTypes
input.ToggleSoftInput(ShowFlags.Forced, HideSoftInputFlags.ImplicitOnly);
}
else
{
//hide keyboard
input.HideSoftInputFromWindow(_view.View.WindowToken, HideSoftInputFlags.None);
}
}
public void UpdateKeyboardState(IInputElement element)
{
var focusedElement = element;
bool oldValue = NeedsKeyboard(_lastFocusedElement);
bool newValue = NeedsKeyboard(focusedElement);
if (newValue != oldValue || newValue)
{
TryShowHideKeyboard(focusedElement, newValue);
}
_lastFocusedElement = element;
}
public void ActivateAutoShowKeyboard()
{
var kbDevice = (KeyboardDevice.Instance as INotifyPropertyChanged);
//just in case we've called more than once the method
kbDevice.PropertyChanged -= KeyboardDevice_PropertyChanged;
kbDevice.PropertyChanged += KeyboardDevice_PropertyChanged;
}
private void KeyboardDevice_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(KeyboardDevice.FocusedElement))
{
UpdateKeyboardState(KeyboardDevice.Instance.FocusedElement);
}
}
public void Dispose()
{
HandleEvents = false;
}
}
}