How can i detect key events in xamarin.forms?

Is there any way to detect key events from a physical keyboard on UWP project?, or its posible to create a custom renderer and assign "onkeydown event" to it?

Best Answers

Answers

  • AdrianKnightAdrianKnight USMember ✭✭✭✭

    I don't think there is a cross-platform way to detect keys. You'll need to do this in custom renderers. You might be looking at KeyEventArgs: http://stackoverflow.com/questions/37969553/detect-arrow-keys-inside-the-window-uwp

  • LuisDuenasLuisDuenas USMember ✭✭
    edited October 2016

    thanks for reply, any idea how can i do that custom renderer?, i have tried for hours with no results

  • AdrianKnightAdrianKnight USMember ✭✭✭✭

    Are you trying to detect keys on an Entry or some other control?

  • LuisDuenasLuisDuenas USMember ✭✭

    this is my scenario:
    i have a master detail page, i want to press ESC and return to another page, i also want to detect F1,F2,F3,...,F12 to assign different functions , thanks for the help

  • AdrianKnightAdrianKnight USMember ✭✭✭✭

    Instead of ContentPage, you could use MasterDetailPage. It should work although I typed it all without running it in an IDE.

  • TiesTies NLMember ✭✭

    AdrianKnight, thnx for your ansure. I'm getting the error that the control is null. Do you know how to fix this or why this is null?

  • delphianQdelphianQ Member
    edited December 2018

    This may help anyone who is having difficulty getting the accepted answer to work.

    using BeforeOurTime.MobileApp.Pages.Explore;
    using BeforeOurTime.MobileApp.UWP.Pages.Explore;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Windows.UI.Xaml;
    using Xamarin.Forms;
    using Xamarin.Forms.Platform.UWP;
    
    [assembly: ExportRenderer(typeof(ExplorePage), typeof(CustomExplorePageRenderer))]
    namespace BeforeOurTime.MobileApp.UWP.Pages.Explore
    {
        public class CustomExplorePageRenderer : PageRenderer
        {
            /// <summary>
            /// Monitor windows core ui keypress when ExplorePage is showing
            /// </summary>
            public CustomExplorePageRenderer() : base()
            {
                // When ExplorePage appears then attach to the ui core keydown event
                Loaded += (object sender, RoutedEventArgs e) =>
                {
                    Windows.UI.Core.CoreWindow.GetForCurrentThread().KeyDown += HandleKeyDown;
                };
                // When ExplorePage disappears then detach from the ui core keydown event
                Unloaded += (object sender, RoutedEventArgs e) =>
                {
                    Windows.UI.Core.CoreWindow.GetForCurrentThread().KeyDown -= HandleKeyDown;
                };
            }
            /// <summary>
            /// Forward a keypress to an ExplorePage method
            /// </summary>
            /// <param name="window"></param>
            /// <param name="e"></param>
            public void HandleKeyDown(Windows.UI.Core.CoreWindow window, Windows.UI.Core.KeyEventArgs e)
            {
                (Element as ExplorePage).KeyPressed(Element, new KeyEventArgs { Key = e.VirtualKey.ToString() });
            }
        }
    }
    

    Note: ExplorePage is checking to see if any child control has focus before processing the key down!

  • ClayBrinleeClayBrinlee USMember ✭✭

    Another way might be something like:

    within your shared project

    create an Inteface called IKeyboardListener that is public

    Within the page's code behind (or viewmodel) where you want to listen for code event add the following:

    MessagingCenter.Subscribe<IKeyboardListener, string>(this, "KeyboardListener", (sender, args) => {
        Debug.WriteLine(args);
    });
    

    in UWP's App.xaml.cs

    at the top add:
    using forms = Xamarin.Forms;

    add the interface to your sealed class:

    sealed partial class App : Application, IKeyboardListener
    {
    ...etc
    

    Add this line to the end of the OnLaunced:

    protected override void OnLaunched(LaunchActivatedEventArgs e)
    {
        ...
    // very last line
        Windows.UI.Core.CoreWindow.GetForCurrentThread().KeyDown += HandleKeyDown;
     }
    

    add this method somewhere in the class:

     public void HandleKeyDown(Windows.UI.Core.CoreWindow window, Windows.UI.Core.KeyEventArgs e)
     {
        forms.MessagingCenter.Send<IKeyboardListener, string>(this, "KeyboardListener", e.VirtualKey.ToString());
     }
    

    Conclusion

    You can implement similar methods within other native projects. Like with Android

    Android is easier because you can tap into the OnKeyUp (or Down) events right from within MainActivity:

        public override bool OnKeyUp(Keycode keyCode, KeyEvent e)
            {
                forms.MessagingCenter.Send<IKeyboardListener, string>(this, "KeyboardListener", keyCode.ToString());
            }
    

    I'm not sure if this has any drawbacks other than maybe unsubscribing to the MessagingCenter listener in the case of Android but it appears to work.

  • rbiezerbieze Member ✭✭

    @ClayBrinlee this works like a charm!

Sign In or Register to comment.