8
votes

Is there any way to check if keyboard is open or not in Xamarin Forms? Are there any events getting fired when the keyboard opens or closes? If so, where can I find an example of it?

2

2 Answers

18
votes

I don't believe that there's a Xamarin.Forms way of doing it. Anyway, for the different platforms (at least Android and iOS) there is a way to achieve what you want.

Android

Under android there is InputMethodManager class. You can obtain it from your activity

var inputMethodManager = (InputMethodManager)this.GetSystemService(Context.InputMethodService);

Now you can check if the keyboard is shown with

var keyboardIsShown = inputMethodManager.IsAcceptingText;

According to this article on CodeProject you can use a class derived from IOnGlobalLayoutListener to listen to global layout events. When this event has fired, you can use the code above to check, if the layout has been changed due to the keyboard popping up.

iOS

Under iOS you may use UIKeyboard class which allows you to observe the DidShowNotification (see here).

notification = UIKeyboard.Notifications.ObserveDidShow ((sender, args) => {
    Debug.WriteLine("Keyboard is shown.");
    // whatever
});

similarly you can observe DidHideNotification (and some others - see here).

Xamarin.Forms

To implement the keyboard-notification in your Xamarin.Forms the easiest way will be to implement platform dependencies which are resolved with the DependencyService. To do this, you'll first have to introduce an interface for the platform service.

public interface IKeyboardService
{
  event EventHandler KeyboardIsShown;
  event EventHandler KeyboardIsHidden;
}

In your platform specific projects you'll have to implement the functionality in a platform specific way. See the following code section for iOS implementation

[assembly: Xamarin.Forms.Dependency(typeof(Your.iOS.Namespace.KeyboardService))]

namespace Your.iOS.Namespace
{
  public class KeyboardService : IKeyboardService
  {
    public event EventHandler KeyboardIsShown;
    public event EventHandler KeyboardIsHidden;

    public KeyboardService()
    {
      SubscribeEvents();
    }

    private void SubscribeEvents()
    {
      UIKeyboard.Notifications.ObserveDidShow(OnKeyboardDidShow);
      UIKeyboard.Notifications.ObserveDidHode(OnKeyboardDidHide);
    }

    private void OnKeyboardDidShow(object sender, EventArgs e)
    {
      KeyboardIsShown?.Invoke(this, EventArgs.Empty);
    }

    private void OnKeyboardDidHide(object sender, EventArgs e)
    {
      KeyboardIsHidden?.Invoke(this, EventArgs.Empty);
    }
  }
}

The Xamarin.Forms.Dependency makes the class visible to the DependencyService. See the following code for Android implementation

[assembly: Xamarin.Forms.Dependency(typeof(Your.Android.Namespace.KeyboardService))]

namespace Your.Android.Namespace
{
  public class KeyboardService : IKeyboardService
  {
    public event EventHandler KeyboardIsShown;
    public event EventHandler KeyboardIsHidden;

    private InputMethodManager inputMethodManager;

    private bool wasShown = false;

    public KeyboardService()
    {
      GetInputMethodManager();
      SubscribeEvents();
    }

    public void OnGlobalLayout(object sender, EventArgs args)
    {
      GetInputMethodManager();
      if(!wasShown && IsCurrentlyShown())
      {
        KeyboardIsShown?.Invoke(this, EventArgs.Empty);
        wasShown = true;
      }
      else if(wasShown && !IsCurrentlyShown())
      {
        KeyboardIsHidden?.Invoke(this, EventArgs.Empty);
        wasShown = false;
      }
    }

    private bool IsCurrentlyShown()
    {
      return inputMethodManager.IsAcceptingText;
    }

    private void GetInputMethodManager()
    {
      if (inputMethodManager == null || inputMethodManager.Handle == IntPtr.Zero)
      {
        inputMethodManager = (InputMethodManager)this.GetSystemService(Context.InputMethodService);
      }
    }

    private void SubscribeEvents()
    {
      ((Activity)Xamarin.Forms.Forms.Context).Window.DecorView.ViewTreeObserver.GlobalLayout += this.OnGlobalLayout;
    }
  }
}

In your Xamarin.Forms app you can now obtain an instance of the correct implementation of IKeyboardService with

var keyboardService = Xamarin.Forms.DependencyService.Get<IKeyboardService>();  
1
votes

In Xamarin Forms in ANDROID CODE change

(InputMethodManager)this.GetSystemService(Context.InputMethodService);

with

 (InputMethodManager)Xamarin.Forms.Forms.Context.GetSystemService(Context.InputMethodService);