【问题标题】:How to dismiss keyboard on button press in Xamarin Forms如何在 Xamarin Forms 中按下按钮时关闭键盘
【发布时间】:2015-08-06 21:02:34
【问题描述】:

经过大量搜索,我找到了一种在 Xamarin Forms 中按下按钮时隐藏键盘的方法,适用于 iOS 案例。所以在下面分享。

如果有人可以改进它,或者为 Android 端分享一个解决方案,那就太好了。

【问题讨论】:

    标签: keyboard xamarin.forms


    【解决方案1】:

    在shared/PCL项目中,添加:

    using System;
    using Xamarin.Forms;
    
    namespace MyApp.Views
    {
        public class ButtonKeyboardHiding : Button {}
    }
    

    在表单中使用此类代替 Button。

    在iOS项目中,添加:

    using System;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.iOS;
    using Foundation;
    using UIKit;
    using MyApp.Views;
    using MyApp.iOS;
    
    [assembly: ExportRenderer ( typeof (ButtonKeyboardHiding), typeof (ButtonKeyboardHidingRenderer ) ) ]
    
    namespace MyApp.iOS
    {
        public class ButtonKeyboardHidingRenderer : ButtonRenderer
        {
            protected override void OnElementChanged ( ElementChangedEventArgs<Button> e )
            {
                base.OnElementChanged  (e );
    
                if ( Control != null ) 
                {   
                    Control.TouchUpInside += ( sender, el ) =>
                    {
                        UIView ctl = Control;
                        while ( true )
                        {
                            ctl = ctl.Superview;
                            if ( ctl.Description.Contains ( "UIView" ) )
                                break;
                        }
                        ctl.EndEditing ( true );
                    };
                }
            }
        }
    }
    

    【讨论】:

    • 您无法遍历 ListView 上的视图似乎很荒谬。谢谢,这个想法。
    • 我试过了,但它不起作用。当我第二次单击按钮时(键盘关闭后),我遇到了异常。
    【解决方案2】:

    这是我为 Android 端隐藏虚拟键盘的解决方案。

    我编写了一个具有 HideKeyboard() 方法的 IKeyboardInteractions 接口。然后我在 MyProject.Droid 中声明一个实现 IKeyboardInteractions 的 KeyboardInteractions 类:

    通用代码:

    public interface IKeyboardInteractions {
        void HideKeyboard();
    }
    

    MyProject.Droid 代码:

    [assembly: Dependency (typeof (KeyboardInteractions))] namespace MyProject.Droid
    {
        public class KeyboardInteractions : IKeyboardInteractions
        {
            public void HideKeyboard()
            {
                var inputMethodManager = Xamarin.Forms.Forms.Context.GetSystemService(Context.InputMethodService) as InputMethodManager;
                if (inputMethodManager != null && Xamarin.Forms.Forms.Context is Activity)
                {
                    var activity = Xamarin.Forms.Forms.Context as Activity;
                    var token = activity.CurrentFocus == null ? null : activity.CurrentFocus.WindowToken;
                    inputMethodManager.HideSoftInputFromWindow(token, 0);
                }
            }
        }
    }
    

    消费方式:

    IKeyboardInteractions keyboardInteractions = DependencyService.Get<IKeyboardInteractions>();
    keyboardInteractions.HideKeyboard ();
    

    【讨论】:

    • 非常感谢尼古拉斯。将在赛道上进行尝试。
    • Xamarin.Forms.Forms.Context 自 XF 2.5 起已弃用。 Android.App.Application.Context 似乎是错误的上下文。你现在用哪一个?
    • @testing 我也是。 Android.App.Application.Context 对我不起作用。只有 Forms.Context 工作
    • 对我来说,Forms.Context 和 Application.Context 都不起作用。起作用的是使用 Plugin.CurrentActivity,其中 var context = CrossCurrentActivity.Current.Activity;
    【解决方案3】:

    我发现这很有用:

    https://forums.xamarin.com/discussion/comment/172077#Comment_172077

    界面:

    public interface IKeyboardHelper
    {
        void HideKeyboard();
    }
    

    iOS:

    public class iOSKeyboardHelper : IKeyboardHelper
    {
        public void HideKeyboard()
        {
            UIApplication.SharedApplication.KeyWindow.EndEditing(true);
        }
    }
    

    机器人:

    public class DroidKeyboardHelper : IKeyboardHelper
    {
        public void HideKeyboard()
        {
            var context = Forms.Context;
            var inputMethodManager = context.GetSystemService(Context.InputMethodService) as InputMethodManager;
            if (inputMethodManager != null && context is Activity)
            {
                var activity = context as Activity;
                var token = activity.CurrentFocus?.WindowToken;
                inputMethodManager.HideSoftInputFromWindow(token, HideSoftInputFlags.None);
    
                activity.Window.DecorView.ClearFocus();
            }
        }
    }
    

    在 Xamarin 表单中的用法:

    DependencyService.Get<IKeyboardHelper>().HideKeyboard();
    

    【讨论】:

    • 您需要在每个 KeyboardHelper 类中的命名空间开始之前使用此行,否则 DependencyService 将找不到它们。[程序集:Xamarin.Forms.Dependency(typeof(xxxxxxKeyboardHelper))]
    • 向 F. Badili 和 JDibble 致敬。
    • 谢谢伙计...真的值得发帖
    • 谢谢你也帮了我。
    【解决方案4】:

    这里是 F. Badili 解决方案的更新版本,它基于 Xamarin Forms 2.5 中的弃用更改。唯一的区别是如何在 Android 类中访问 Context。

    Xamarin Forms 项目中:

    public interface IKeyboardHelper
    {
        void HideKeyboard();
    }   
    

    iOS 项目中:

    using System;
    using Xamarin.Forms;
    using ProjectName;
    using ProjectName.iOS;
    using UIKit;
    
    [assembly: Dependency(typeof(iOSKeyboardHelper))]
    namespace ProjectName.iOS
    {
        public class iOSKeyboardHelper : IKeyboardHelper
        {
            public void HideKeyboard()
            {
                UIApplication.SharedApplication.KeyWindow.EndEditing(true);
            }
        }
    }
    

    Droid 项目中:

    using System;
    using Xamarin.Forms;
    using ProjectName;
    using ProjectName.Droid;
    using Xamarin.Forms.Platform.Android;
    using Android.Views.InputMethods;
    using Android.App;
    using Android.Content;
    
    [assembly: Xamarin.Forms.Dependency(typeof(DroidKeyboardHelper))] 
    namespace ProjectName.Droid
    {
        public class DroidKeyboardHelper : IKeyboardHelper
        {
            public void HideKeyboard()
            {
                var context = Android.App.Application.Context;
                var inputMethodManager = context.GetSystemService(Context.InputMethodService) as InputMethodManager;
                if (inputMethodManager != null && context is Activity)
                {
                    var activity = context as Activity;
                    var token = activity.CurrentFocus?.WindowToken;
                    inputMethodManager.HideSoftInputFromWindow(token, HideSoftInputFlags.None);
    
                    activity.Window.DecorView.ClearFocus();
                }
            }
        }
    }
    

    Xamarin 表单 页面中:

    DependencyService.Get<IKeyboardHelper>().HideKeyboard();
    

    【讨论】:

    • Android.App.Application.Context 对我不起作用。只有 Forms.Context。因为 context is Activity 变假了
    • 对我来说,Forms.Context 和 Application.Context 都不起作用。起作用的是使用 Plugin.CurrentActivity,其中 var context = CrossCurrentActivity.Current.Activity;
    【解决方案5】:

    即使使用 Kenan Casey 的更新,我也无法让 F. Badili 的 Android 解决方案正常工作。进一步谷歌搜索将我带到Dave's Tech Blog 关于Xamarin.Forms.Forms.Context 的弃用。它说Android.App.Application.Context 不是也不能转换为Activty(至少在我的情况下,请参阅博客文章的 cmets 以获得解释)。

    Droid 项目中:

    [assembly: Xamarin.Forms.Dependency(typeof(DroidKeyboardHelper))] 
    namespace ProjectName.Droid{
        public class DroidKeyboardHelper : IKeyboardHelper {
            static Context _context;
    
            public static void Init(Context context) => _context = context;
    
            public void HideKeyboard(){
                var inputMethodManager = _context.GetSystemService(Context.InputMethodService) as InputMethodManager;
                if (inputMethodManager != null && _context is Activity) {
                    var activity = _context as Activity;
                    var token = activity.CurrentFocus?.WindowToken;
                    inputMethodManager.HideSoftInputFromWindow(token, HideSoftInputFlags.None);
    
                    activity.Window.DecorView.ClearFocus();
                }
            }
        }
    }
    

    Droid MainActivity.cs中:

    protected override void OnCreate(Bundle savedInstanceState){
        base.OnCreate(savedInstanceState);
        ...
        KeyboardHelper.Init(this);
        ...
        LoadApplication(new App());
    }
    

    注意

    这仅在您的应用仅在单个 Activity 上运行时才有效。如果在任何情况下您的应用程序有多个活动,请参阅Dave's Tech Blog 以获取适合您情况的正确实施。

    【讨论】:

      【解决方案6】:
       view.Unfocus();
      

      就是这样。

      有些人报告说这不起作用,但对我来说它就像大炮一样。

      【讨论】:

      • Unfocus() 仍在 Android 和 Xamarin Forms v.4.8 上完成这项工作。
      【解决方案7】:

      如果在经过大量搜索后移除焦点方法对您不起作用(并且对我不起作用),我意识到一种强制关闭键盘的简单方法。

      FindViewById<EditText>(Resource.Id.edittextname).Enabled = false;
      FindViewById<EditText>(Resource.Id.edittextname).Enabled = true;
      

      就是这样。只需禁用并启用它,它就会关闭键盘。

      【讨论】:

      • MyEntry.IsEnabled=falseMyEntry.UnFocus() 效果更好。
      • 这比 UIApplication.SharedApplication.KeyWindow.EndEditing(true);View.UnFocus 效果更好
      • 这应该是正确的答案。超级简单,仍然适用于 Xamarin.Forms 5
      【解决方案8】:

      Forms9Patch 具有良好的工作实现。

      所以只需使用整个库 (https://github.com/baskren/Forms9Patch) 或使用来自 Github 存储库 (KeyboardService.cs) 的代码。

      那么使用它就很容易了:

      Forms9Patch.KeyboardService.Hide();
      

      适用于 Android、iOS 和 UWP。

      【讨论】:

        【解决方案9】:

        Xamarin Forms 4.8 背后的代码中的简单解决方案。订阅TextChanged事件,即Editor或Entry,然后查看后面代码中的key。 Le Mot Juiced 回答时,UnFocused() 将关闭键盘。我的示例在按下回车键后关闭键盘,但您可以将另一个键应用于条件。

        XAML

         <Editor TextChanged="Input_TextChanged"></Editor>
        

        背后的代码

        private void Input_TextChanged(object sender, TextChangedEventArgs e)
            {
                char key = string.IsNullOrEmpty(e.NewTextValue) ? ' ' : e.NewTextValue.Last();
                if (key == '\n')
                {
                    var s = (Editor)sender;
                    s.Text = e.OldTextValue ?? string.Empty;
                    s.Unfocus();
                }
            }
        

        【讨论】:

          【解决方案10】:

          我遇到了一个问题,即适用于 Android 的 TapGestureRecognizer 的键盘没有关闭。为了解决这个问题,我不得不用一个按钮替换 Span。下面注释掉的代码在关闭键盘方面对我不起作用。在 Android 中单击按钮时键盘会自动关闭。

                         <Button VerticalOptions="Center" Text="Login" Command="{Binding LoginCommand}"/>
          
                      <!--
                      <StackLayout Grid.Row="2" Padding="20">
                          <Label HorizontalOptions="Center">
                              <Label.FormattedText>
                                  <FormattedString>
                                      <Span Text="Login" TextColor="Blue">
                                          <Span.GestureRecognizers>
                                              <TapGestureRecognizer Command="{Binding LoginCommand}"/>
                                          </Span.GestureRecognizers>
                                      </Span>
                                  </FormattedString>
                              </Label.FormattedText>
                          </Label>
                      </StackLayout>
                      -->
          

          【讨论】:

            【解决方案11】:

            UnFocus() 对我有用,但有一些注意事项。

            我有两个页面:EditPage 有一个 Entry 控件,当获得焦点时,它会显示键盘。 ListPage 没有 Entry 字段。 当 EditPage 被显示并且 Entry 聚焦时,键盘被显示。如果我现在导航到 ListPage,键盘仍然显示。

            为了解决,我尝试了这些:

            1.) 在 ListPage.OnAppearing() 中,我添加了对 Unfocus() 的调用。

            愚蠢,因为此时没有任何重点,但如果这是隐藏键盘的方式,值得一试。此外,无论我们来自何处,此页面都应负责显示或隐藏键盘。

            没用。

            2.) 在 EditPage.OnDisappearing() 中,我像这样添加了 Unfocus():

            protected override void OnDisappearing()
            {
                Unfocus();
                base.OnDisappearing();
            }
            

            这行得通。

            【讨论】:

              【解决方案12】:

              您可以为输入字段命名。例如Entryfield1EntryField2 是显示键盘的条目。然后用OnDisappearing 覆盖页面事件,如下所示:

              protected override void OnDisappearing()
              {
                  Entryfield1.Unfocus();
                  EntryField2.Unfocus();
                  base.OnDisappearing();
              }
              

              【讨论】:

                猜你喜欢
                • 2019-03-08
                • 2023-03-10
                • 1970-01-01
                • 1970-01-01
                • 2019-02-18
                • 2019-10-06
                • 1970-01-01
                • 2015-02-27
                • 2013-06-13
                相关资源
                最近更新 更多