16

After much searching, I worked out a way to hide the keyboard on a button press in Xamarin Forms for iOS. So it's shared below.

If anyone can improve it, or share a solution for the Android side, that would be great.

13 Answers 13

25

I found this useful:

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

Interface:

public interface IKeyboardHelper
{
    void HideKeyboard();
}

iOS:

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

Droid:

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();
        }
    }
}

Usage in Xamarin Forms:

DependencyService.Get<IKeyboardHelper>().HideKeyboard();
Sign up to request clarification or add additional context in comments.

3 Comments

You need this line before the start of the namespace in each of your KeyboardHelper classes or the DependencyService will not find them.[assembly: Xamarin.Forms.Dependency(typeof(xxxxxxKeyboardHelper))]
KUDOS to both F. Badili and JDibble.
Dont work with android
12

If the removing focus method is not working for you (and it wasn't working for me) after a lot of searching I realized an easy way to force the keyboard to dismiss.

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

That's it. Just disable and enable it and it will close the keyboard.

4 Comments

MyEntry.IsEnabled=false works better than MyEntry.UnFocus().
This worked better than UIApplication.SharedApplication.KeyWindow.EndEditing(true); and View.UnFocus
This should be the correct answer. Super simple and still works on Xamarin.Forms 5
Taking Frank Hintsch' approach I used (in Maui) ((Entry)sender).isEnabled=false; ((Entry)sender).isEnabled=true;
9
 view.Unfocus();

That's it.

Some people report this not working, but it's worked like gangbusters for me.

1 Comment

Unfocus() still getting the job down on Android & Xamarin Forms v.4.8.
7

Here's an updated version of F. Badili's solution based on a deprecating change in Xamarin Forms 2.5. The only difference is how the Context is accessed in the Android class.

In the Xamarin Forms project:

public interface IKeyboardHelper
{
    void HideKeyboard();
}   

In the iOS project:

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);
        }
    }
}

In the Droid Project:

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();
            }
        }
    }
}

In Xamarin Forms page:

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

2 Comments

Android.App.Application.Context didn't work for me. Only the Forms.Context. Because context is Activity getting false
For me, neither Forms.Context nor Application.Context worked. What did work was to use Plugin.CurrentActivity, with var context = CrossCurrentActivity.Current.Activity;
5

This is my solution to hide the virtual keyboard for the Android side.

I coded a IKeyboardInteractions interface which has a HideKeyboard() method. Then I declare a KeyboardInteractions class in MyProject.Droid which implements IKeyboardInteractions :

Common code :

public interface IKeyboardInteractions {
    void HideKeyboard();
}

MyProject.Droid code:

[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);
            }
        }
    }
}

Consuming method:

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

4 Comments

Thanks so much Nicholas. Will be trying it out down the track.
Xamarin.Forms.Forms.Context is deprecated since XF 2.5. Android.App.Application.Context seems to be the wrong context. Which one do you use now?
@testing me too. Android.App.Application.Context didn't work for me. Only the Forms.Context working
For me, neither Forms.Context nor Application.Context worked. What did work was to use Plugin.CurrentActivity, with var context = CrossCurrentActivity.Current.Activity;
5

I couldn't get F. Badili's solution for Android to work even with Kenan Casey's update on it. Further googling took me to Dave's Tech Blog regarding the deprecation of Xamarin.Forms.Forms.Context. It says Android.App.Application.Context is not and can't be converted to Activty (at least in my case, refer to the blog post's comments for the explanation).

In the Droid Project:

[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();
            }
        }
    }
}

In the Droid MainActivity.cs:

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

NOTE:

This will only work if your app only runs on a single activity. If in any case your app has multiple activity, please refer to Dave's Tech Blog for a proper implementation for your case.

Comments

3

You can give a name to the entry fields. For instance Entryfield1 and EntryField2 are the entries that showed the keyboard. Then override the Page Events with OnDisappearing like below:

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

Comments

2

In the shared/PCL project, add:

using System;
using Xamarin.Forms;

namespace MyApp.Views
{
    public class ButtonKeyboardHiding : Button {}
}

Use this class in place of Button in your forms.

In the iOS project, add:

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 );
                };
            }
        }
    }
}

2 Comments

Seems ridiculous that you can't iterate through the views on a ListView. Thanks, for this idea.
I tried, but it's not working. And when I click the button a 2nd time (after keyboard closes), I'm getting an exception.
1

Forms9Patch has a good working implementation.

So just use the whole library (https://github.com/baskren/Forms9Patch) or use their code from the Github repo (KeyboardService.cs).

Using it is quite easy then:

Forms9Patch.KeyboardService.Hide();

Available for Android, iOS and UWP.

Comments

0

Simple solution in code behind Xamarin Forms 4.8. Subscribe to TextChanged event, i.e. Editor or Entry, then check the key in the code behind. As Le Mot Juiced answered, UnFocused() will close the keyboard. My example closes the keyboard after the enter key is pressed, but you can apply another key to the condition.

XAML

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

Code behind

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();
        }
    }

1 Comment

Well focus is lost, but it doesn't seem to make keyboard disappear? (I use this on a simple Entry element and adapted).
0

I had an issue where the keyboard was not closing for a TapGestureRecognizer for Android. To fix this I had to replace the Span with a button. Commented out code below is what was not working for me in terms of closing the keyboard. Keyboard was automatically closed on clicking the button in 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>
            -->

Comments

0

UnFocus() worked for me, with some caveats.

I had two pages: EditPage had an Entry control, that, when focused, displayed the keyboard. ListPage had no Entry field. When EditPage was displayed, and the Entry focused, the keyboard was displayed. If I now navigated to ListPage, the keyboard remained displayed.

To resolve, I tried these:

1.) In ListPage.OnAppearing() I added a call to Unfocus().

Silly, as there is nothing focused at this point, but if this is the way to hide the keyboard, was worth a try. Also, this page should be responsible for showing or hideing the keyboard, no matter where we caome from.

Didn't work.

2.) In EditPage.OnDisappearing(), I added Unfocus() like so:

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

This works.

Comments

0

The best way i have found, API > 30 is to create an instance of MainActivity as a static resource:

internal static MainActivity Instance { get; private set; }

And then to reference it and hide the InsetsController that handles media entry:

MainActivity.Instance.Window.InsetsController.Hide(WindowInsets.Type.Ime());

This can be done using Dependency Service if using multi platform:

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

The reverse can be done to show the keyboard at any time:

MainActivity.Instance.Window.InsetsController.Show(WindowInsets.Type.Ime());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.