Запись 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)
{
}
Другие вопросы по тегам