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