Запись Xamarin.Forms, которая не должна показывать SoftKeyboard в фокусе
Я работаю над проектом Xamarin Forms и использую представление Entry, и это требование, так как мне нужно иметь возможность сосредоточиться на нем, но также необходимо не показывать программную клавиатуру.
Это требование не может быть изменено. Кроме того, я не могу использовать метку или кнопку вместо ввода, поскольку они не получают фокус.
После этой статьи ( https://theconfuzedsourcecode.wordpress.com/2017/05/19/a-keyboard-disabled-entry-control-in-xamarin-forms/comment-page-1/) я попытался создание пользовательского рендерера и использование ShowSoftInputOnFocus на Android, но это ненадолго покажет, а затем скроет программную клавиатуру. Это не вариант, так как мое требование строго не показывать программную клавиатуру в этом настраиваемом поле ввода вообще.
Итак, я создал свой обычай KeyboardlessEntry
в проекте Xamarin.Forms (.NET Standard 2.0):
namespace MyProjNamespace
{
public class KeyboardlessEntry : Entry
{
}
}
а потом мой обычай KeyboardlessEntryRenderer
рендер в Xamarin.Droid головной проект вроде так:
[assembly: ExportRenderer(typeof(KeyboardlessEntry), typeof(KeyboardlessEntryRenderer))]
namespace MyProjNamespace.Droid
{
public class KeyboardlessEntryRenderer : EntryRenderer
{
//as of latest Xamarin.Forms need to provide c-tor that
//receives Android Context and sets it in base
public KeyboardlessEntryRenderer (Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
if (e.NewElement != null)
{
((KeyboardlessEntry)e.NewElement).PropertyChanging += OnPropertyChanging;
}
if (e.OldElement != null)
{
((KeyboardlessEntry)e.OldElement).PropertyChanging -= OnPropertyChanging;
}
this.Control.ShowSoftInputOnFocus = false; // disable soft keyboard on focus
}
private void OnPropertyChanging(object sender, PropertyChangingEventArgs propertyChangingEventArgs)
{
if (propertyChangingEventArgs.PropertyName == VisualElement.IsFocusedProperty.PropertyName)
{
// fully dismiss the soft keyboard
InputMethodManager imm = (InputMethodManager)this.Context.GetSystemService(Context.InputMethodService);
imm.HideSoftInputFromWindow(this.Control.WindowToken, 0);
}
}
}
}
Как видите, я устанавливаю ShowSoftInputOnFocus
в OnElementChanged
переопределить, но это не мешает его показу по какой-то причине. Моя клавиатура по-прежнему отображается на KeyboardlessEntry
Фокус, а затем исчезает, потому что я звоню HideSoftInputFromWindow
внутри OnPropertyChanging
событие.
Я не уверен, почему это не работает. Я ожидаю, что установка ShowSoftInputOnFocus
значение false, как я делал выше, отключило бы показ программной клавиатуры полностью. Некоторые люди утверждают, что это работает на Android или Xamarin.Android, но не работает в Xamarin.Forms.
Аналогичная проблема на iOS, вот рендер для iOS
[assembly: ExportRenderer (typeof (KeyboardlessEntry), typeof (KeyboardlessEntryRenderer))] пространство имен Squirrel.FoH.App.iOS.Implementations.Controls {открытый класс KeyboardlessEntryRenderer: EntryRenderer { public KeyboardlessEntryRenderer)
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
this.Control.InputView = new UIView(); // disable soft keyboard
}
}
}
Это также показывает, а затем уменьшает клавиатуру до полосы ниже, но обратите внимание, что нет кнопки, чтобы закрыть ее полностью, что делает ее еще более раздражающей
2 ответа
Я создал эффект, чтобы достичь этого.
Это добавит / удалит возможность показа клавиатуры в зависимости от того, как вы установили EnableKeyboardProperty для эффекта.
В общем проекте:
using System.Linq;
using Xamarin.Forms;
namespace Sample.Effects
{
/// <summary>
/// Enable Keyboard Effect
/// </summary>
public class KeyboardEnableEffect : RoutingEffect
{
/// <inheritdoc />
public KeyboardEnableEffect() : base("Sample.KeyboardEnableEffect")
{
}
}
/// <summary>
/// Set up Bindable Properties for KeyboardEnableEffect
/// </summary>
public static class EnableKeyboardEffect
{
/// <summary>
/// Bindable property to Enable keyboard
/// </summary>
public static readonly BindableProperty EnableKeyboardProperty =
BindableProperty.Create("EnableKeyboard", typeof(bool), typeof(EnableKeyboardEffect), false, propertyChanged: OnEnableKeyboardChanged);
/// <summary>
/// Get EnableKeyboard value
/// </summary>
/// <param name="view"></param>
/// <returns></returns>
public static bool GetEnableKeyboard(BindableObject view)
{
return (bool)view.GetValue(EnableKeyboardProperty);
}
/// <summary>
/// Set EnableKeyboard Value
/// </summary>
/// <param name="view"></param>
/// <param name="value"></param>
public static void SetEnableKeyboard(BindableObject view, bool value)
{
view.SetValue(EnableKeyboardProperty, value);
}
private static void OnEnableKeyboardChanged(BindableObject bindable, object oldValue, object newValue)
{
if (!(bindable is View view))
{
return;
}
var enableKeyboard = (bool)newValue;
if (enableKeyboard)
{
var toRemove = view.Effects.FirstOrDefault(e => e is KeyboardEnableEffect);
if (toRemove != null)
{
view.Effects.Remove(toRemove);
}
}
else
{
view.Effects.Add(new KeyboardEnableEffect());
}
}
}
}
В Android:
using System;
using System.Linq;
using Android.App;
using Android.Content;
using Android.Views.InputMethods;
using Android.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using View = Android.Views.View;
[assembly: ExportEffect(typeof(Sample.Droid.Effects.KeyboardEnableEffect), nameof(Sample.Droid.Effects.KeyboardEnableEffect))]
namespace Sample.Droid.Effects
{
public class KeyboardEnableEffect : PlatformEffect
{
private static Activity _activity;
public static void Init(Activity activity)
{
_activity = activity;
}
protected override void OnAttached()
{
try
{
if (!(Control is EditText editText))
{
return;
}
editText.ShowSoftInputOnFocus = EnableKeyboardEffect.GetEnableKeyboard(Element);
if (!editText.ShowSoftInputOnFocus)
{
editText.FocusChange += HideMethod;
}
editText.RequestFocus();
}
catch (Exception ex)
{
GlobalException.HandleExceptionAsync(ex);
}
}
protected override void OnDetached()
{
try
{
if (Element == null || Control == null)
{
return;
}
if (!(Control is EditText editText))
{
return;
}
var visibilityEffect = Element.Effects.OfType<Sample.Effects.KeyboardEnableEffect>().FirstOrDefault();
if (visibilityEffect != null)
{
return;
}
editText.ShowSoftInputOnFocus = EnableKeyboardEffect.GetEnableKeyboard(Element);
editText.FocusChange -= HideMethod;
var imm = (InputMethodManager)_activity?.GetSystemService(Context.InputMethodService);
//Comment out as it is using an obsolete method
//imm?.ShowSoftInputFromInputMethod(Control.WindowToken, ShowFlags.Implicit);
imm?.ShowSoftInput(Control, ShowFlags.Implicit);
editText.RequestFocus();
}
catch (Exception ex)
{
GlobalException.HandleExceptionAsync(ex);
}
}
private void HideMethod(object sender, View.FocusChangeEventArgs e)
{
try
{
//hide keyboard for current focused control.
var imm = (InputMethodManager)_activity?.GetSystemService(Context.InputMethodService);
imm?.HideSoftInputFromWindow(Control.WindowToken, HideSoftInputFlags.None);
}
catch (Exception ex)
{
GlobalException.HandleExceptionAsync(ex);
}
}
}
}
Пример использования: в вашем Xaml вам нужно будет привязать эффект к вашему элементу управления следующим образом:
<Entry sampleEffects:EnableKeyboardEffect.EnableKeyboard="False"
<Entry.Effects>
<sampleEffects:KeyboardEnableEffect />
</Entry.Effects>
</Entry>
Попробуйте добавить это в свой KeyboardlessEntryRenderer
учебный класс:
public KeyboardlessEntryRenderer (Context context) : base(context)
{
}