在 Xamarin 中隐藏软键盘

Hide softkeyboard in Xamarin

在 Xamarin.forms 可移植表单项目中聚焦 Entry 时,如何隐藏显示的软键盘?我假设我们必须为此编写特定于平台的渲染器,但以下内容不起作用:

我创建了自己的入口子类:

public class MyExtendedEntry : Entry
{
}

然后在 xamarin.android 项目中我的渲染器:

public class MyExtendedEntryRenderer : EntryRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
    {
        base.OnElementChanged(e);
        if (Control != null)
        {
            new Handler().Post(delegate
            {
                var imm = (InputMethodManager)Control.Context.GetSystemService(Context.InputMethodService);
                var result = imm.HideSoftInputFromWindow(Control.WindowToken, 0);
            });
        }
    }
}

OnElementChanged 按预期调用,当使用 Handler.Post() 时,我还得到一个 WindowToken 而不是 null。遗憾的是 HideSoftInputFromWindow 中的 return 值始终为 false,并且在单击条目时软键盘仍然出现。

OnElementChanged 在初始化视图并附加到视图时调用。您想要做的是在单击条目时隐藏键盘,因此您应该将事件处理程序添加到 FocusChangeControl.

示例:

    protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
    {
        base.OnElementChanged(e);
        if (Control != null)
        {
            Control.Click += (sender, evt) => {
                new Handler().Post(delegate
                    {
                        var imm = (InputMethodManager)Control.Context.GetSystemService(Android.Content.Context.InputMethodService);
                        var result = imm.HideSoftInputFromWindow(Control.WindowToken, 0);

                        Console.WriteLine(result);
                    });
            };

            Control.FocusChange += (sender, evt) => {
                new Handler().Post(delegate
                    {
                        var imm = (InputMethodManager)Control.Context.GetSystemService(Android.Content.Context.InputMethodService);
                        var result = imm.HideSoftInputFromWindow(Control.WindowToken, 0);

                        Console.WriteLine(result);
                    });
            };
        }
    }

更新: @Vikram 的综合回答

更新: 添加了 Click 事件处理程序

注意:我不熟悉 Xamarin。

根据我的经验,在控件获得焦点后立即使用 imm.HideSoftInputFromWindow(Control.WindowToken, 0) 会产生不可靠的结果,即使在使用 Post 时也是如此。我改用 PostDelayed 取得了成功。我使用的延迟是 500ms。

试一试:

public class MyExtendedEntryRenderer : EntryRenderer
{
    protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
    {
        base.OnElementChanged(e);
        if (Control != null)
        {
            new Handler().PostDelayed(delegate
            {
                var imm = (InputMethodManager)Control.Context.GetSystemService(Context.InputMethodService);
                var result = imm.HideSoftInputFromWindow(Control.WindowToken, 0);
            }, 500L);
        }
    }
}

防止虚拟键盘出现的关键是重写Entry的Focus()方法,不调用基方法。否则它总会偶尔出现,不管你做什么。这具有简化所需代码的额外好处,因为您可以自动控制虚拟键盘的外观和消失。到目前为止,我还没有发现这种方法有任何负面影响。

我创建了一个可以完全控制虚拟键盘的示例控件和一个显示用法的小应用程序。

由于这个问题在几个论坛上被问到,我决定写一个详细的自述文件附加到项目,解释实施的所有关键点,而不是在几个不同的论坛上重复解释。我希望没关系。如果没有,请告诉我。

整个项目可在此处获得: https://github.com/UweReisewitz/XamarinAndroidEntry