Browse Source

Android preedit

feature/ImePreeditText
Benedikt Stebner 4 years ago
parent
commit
ab6df8c9ed
  1. 22
      src/Android/Avalonia.Android/AndroidInputMethod.cs
  2. 4
      src/Android/Avalonia.Android/IInitEditorInfo.cs
  3. 56
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  4. 4
      src/Avalonia.Base/Input/TextInput/ITextInputMethodImpl.cs
  5. 2
      src/Avalonia.Base/Media/FontFamily.cs

22
src/Android/Avalonia.Android/AndroidInputMethod.cs

@ -1,10 +1,14 @@
using System;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Text;
using Android.Views;
using Android.Views.InputMethods;
using Avalonia.Android.Platform.SkiaPlatform;
using Avalonia.Input;
using Avalonia.Input.TextInput;
using Java.Lang;
namespace Avalonia.Android
{
@ -13,6 +17,8 @@ namespace Avalonia.Android
{
private readonly TView _host;
private readonly InputMethodManager _imm;
private ITextInputMethodClient _client;
private InputConnectionImpl _inputConnection;
public AndroidInputMethod(TView host)
{
@ -27,6 +33,10 @@ namespace Avalonia.Android
_host.ViewTreeObserver.AddOnGlobalLayoutListener(new SoftKeyboardListener(_host));
}
public bool IsActive => Client != null;
public ITextInputMethodClient Client => _client;
public void Reset()
{
_imm.RestartInput(_host);
@ -34,16 +44,16 @@ namespace Avalonia.Android
public void SetClient(ITextInputMethodClient client)
{
var active = client is { };
_client = client;
if (active)
if (IsActive)
{
_host.RequestFocus();
Reset();
_imm.ShowSoftInput(_host, ShowFlags.Implicit);
}
else
_imm.HideSoftInputFromWindow(_host.WindowToken, HideSoftInputFlags.None);
_imm.HideSoftInputFromWindow(_host.WindowToken, HideSoftInputFlags.None);
}
public void SetCursorRect(Rect rect)
@ -52,7 +62,9 @@ namespace Avalonia.Android
public void SetOptions(TextInputOptions options)
{
_host.InitEditorInfo((outAttrs) =>
_inputConnection = new InputConnectionImpl(_host, this);
_host.InitEditorInfo((_host, outAttrs) =>
{
outAttrs.InputType = options.ContentType switch
{
@ -74,6 +86,8 @@ namespace Avalonia.Android
outAttrs.InputType |= global::Android.Text.InputTypes.TextFlagMultiLine;
outAttrs.ImeOptions |= ImeFlags.NoFullscreen | ImeFlags.NoExtractUi;
return _inputConnection;
});
}

4
src/Android/Avalonia.Android/IInitEditorInfo.cs

@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
using Android.Views;
using Android.Views.InputMethods;
using Avalonia.Android.Platform.SkiaPlatform;
namespace Avalonia.Android
{
interface IInitEditorInfo
{
void InitEditorInfo(Action<EditorInfo> init);
void InitEditorInfo(Func<View, EditorInfo, InputConnectionImpl> init);
}
}

56
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -3,6 +3,9 @@ using System.Collections.Generic;
using Android.Content;
using Android.Graphics;
using Android.Media.TV;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Views.InputMethods;
using Avalonia.Android.OpenGL;
@ -21,6 +24,7 @@ using Avalonia.Platform;
using Avalonia.Platform.Storage;
using Avalonia.Rendering;
using Avalonia.Rendering.Composition;
using Java.Lang;
namespace Avalonia.Android.Platform.SkiaPlatform
{
@ -148,7 +152,8 @@ namespace Avalonia.Android.Platform.SkiaPlatform
{
private readonly TopLevelImpl _tl;
private Size _oldSize;
public ViewImpl(Context context, TopLevelImpl tl, bool placeOnTop) : base(context)
public ViewImpl(Context context, TopLevelImpl tl, bool placeOnTop) : base(context)
{
_tl = tl;
if (placeOnTop)
@ -187,7 +192,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
return res != null ? res.Value : baseResult;
}
void ISurfaceHolderCallback.SurfaceChanged(ISurfaceHolder holder, Format format, int width, int height)
{
var newSize = new PixelSize(width, height).ToSize(_tl.RenderScaling);
@ -206,9 +210,10 @@ namespace Avalonia.Android.Platform.SkiaPlatform
return true;
}
private Action<EditorInfo> _initEditorInfo;
private Func<View, EditorInfo, InputConnectionImpl> _initEditorInfo;
protected InputConnectionImpl _inputConnection;
public void InitEditorInfo(Action<EditorInfo> init)
public void InitEditorInfo(Func<View, EditorInfo, InputConnectionImpl> init)
{
_initEditorInfo = init;
}
@ -216,9 +221,11 @@ namespace Avalonia.Android.Platform.SkiaPlatform
public sealed override IInputConnection OnCreateInputConnection(EditorInfo outAttrs)
{
if (_initEditorInfo != null)
_initEditorInfo(outAttrs);
return base.OnCreateInputConnection(outAttrs);
{
return _initEditorInfo(this, outAttrs);
}
return null;
}
}
@ -249,4 +256,39 @@ namespace Avalonia.Android.Platform.SkiaPlatform
throw new NotImplementedException();
}
}
internal class InputConnectionImpl: BaseInputConnection
{
private readonly ITextInputMethodImpl _inputMethod;
public InputConnectionImpl(View? targetView, ITextInputMethodImpl inputMethod) :
base(targetView, false)
{
_inputMethod = inputMethod;
}
public InputConnectionImpl(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
public override bool SetComposingText(ICharSequence text, int newCursorPosition)
{
if (_inputMethod.IsActive)
{
_inputMethod.Client.SetPreeditText(text.ToString());
}
return base.SetComposingText(text, newCursorPosition);
}
public override bool CommitText(ICharSequence text, int newCursorPosition)
{
if (_inputMethod.IsActive)
{
_inputMethod.Client.SetPreeditText(null);
}
return base.CommitText(text, newCursorPosition);
}
}
}

4
src/Avalonia.Base/Input/TextInput/ITextInputMethodImpl.cs

@ -5,6 +5,10 @@ namespace Avalonia.Input.TextInput
[Unstable]
public interface ITextInputMethodImpl
{
ITextInputMethodClient Client { get; }
bool IsActive { get; }
void SetClient(ITextInputMethodClient? client);
void SetCursorRect(Rect rect);
void SetOptions(TextInputOptions options);

2
src/Avalonia.Base/Media/FontFamily.cs

@ -128,7 +128,7 @@ namespace Avalonia.Media
default:
{
throw new ArgumentException("Specified family is not supported.");
return new FontFamilyIdentifier(name, null);
}
}
}

Loading…
Cancel
Save