Prevent Keyboard From Showing on Entry Focus

dinobdinob USUniversity ✭✭✭
edited November 2018 in Xamarin.Forms

I need to be able to scan into a Xamarin Forms Entry view repeatedly without showing keyboard.

Since I need to receive focus for this, Label or Button views are not an option, so I need to use Entry view.

I tried creating custom renderer and using ShowSoftInputOnFocus on Android and InputView on IOS. But that still shows, then hides soft keyboard, so not good. I dont want to show it at all.

I would expect this renderer to work fine as I am setting ShowSoftInputOnFocus to false but again, the keyboard still shows, then disappears

My custom Entry:

namespace MyProjNamespace
{
    public class KeyboardlessEntry : Entry
    {
    }
}

My custom entry renderer:

[assembly: ExportRenderer(typeof(KeyboardlessEntry), typeof(KeyboardlessEntryRenderer))]
namespace MyProjNamespace.Droid
{
    public class KeyboardlessEntryRenderer : EntryRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement != null)
            {
                ((KeyboardlessEntry)e.NewElement).PropertyChanging += OnPropertyChanging;
            }

            if (e.OldElement != null)
            {
                ((KeyboardlessEntry)e.OldElement).PropertyChanging -= OnPropertyChanging;
            }

            this.Control.ShowSoftInputOnFocus = false; // disable soft keyboard on focus
        }

        private void OnPropertyChanging(object sender, PropertyChangingEventArgs propertyChangingEventArgs)
        {
            if (propertyChangingEventArgs.PropertyName == VisualElement.IsFocusedProperty.PropertyName)
            {
                // fully dismiss the soft keyboard 
                InputMethodManager imm = (InputMethodManager)this.Context.GetSystemService(Context.InputMethodService);
                imm.HideSoftInputFromWindow(this.Control.WindowToken, 0);
            }
        }
    }
}

Answers

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭

    Scan means scan barcodes? Why you need to use an Entry?

  • dinobdinob USUniversity ✭✭✭
    edited November 2018

    @AlessandroCaliaro said:
    Scan means scan barcodes? Why you need to use an Entry?

    What else are you suggesting? I thought about Label and Button as hidden views but these dont receive input. Not sure why not Entry? If you are suggesting Xing, that is not an option as it is very slow, we cannot use camera for scanning. We use external barcode scanners, bluetooth connected.
    I also thought to capture scan on the ContentView or Page level but that seam to be impossible. In WinForms, that was fine but not in Xamarin. For that reason, I capture scan on Entry focus. If item is scanned on Entry that is in focus, scan is captured and triggers Enter key, which then handles search for scanned item.
    Not sure if that answers your question but if you have some better suggestions, please share. Also, we dont use camera scanning or SDK scanning as there are no SDKs available for all 3 platforms, so we use old style data wedge (basically, same as keyboard scan).

  • stemadostemado Member ✭✭✭

    @dinob here is the logic implemented by multiple users in the forums to achieve this effect, though the code below provides custom renderers for Android only:

    Attached is the entire project provided by @KayKuo in the following forum discussion with @fernandopV2 : https://forums.xamarin.com/discussion/comment/347010#Comment_347010

  • AlessandroCaliaroAlessandroCaliaro ITMember ✭✭✭✭✭
    I think you should not use keyboard emulation. Try with SPP and Bluetooth sockets
  • dinobdinob USUniversity ✭✭✭

    @AlessandroCaliaro said:
    I think you should not use keyboard emulation. Try with SPP and Bluetooth sockets

    Thans but I believe we talked about this few months ago. I believe you wrote an article on it but you also commented that you never were able to implement it on IOS and UWP side. I read your article and talked to you back and forth on this several times. I also was not able to find solution for IOS and UWP and using emulation seemed to be valid solution (and still seams to be) for simple scanning. Thanks anyways.

  • dinobdinob USUniversity ✭✭✭
    edited November 2018

    @stemado said:
    @dinob here is the logic implemented by multiple users in the forums to achieve this effect, though the code below provides custom renderers for Android only:

    Attached is the entire project provided by @KayKuo in the following forum discussion with @fernandopV2 : https://forums.xamarin.com/discussion/comment/347010#Comment_347010

    @stemado Thanks but this solution shows keyboard, then hides it. I am looking for solution to not show it at all when custom Entry receives the focus. Showing it then hiding it based on entry makes things even worse.

  • dinobdinob USUniversity ✭✭✭

    @stemado said:
    @dinob here is the logic implemented by multiple users in the forums to achieve this effect, though the code below provides custom renderers for Android only:

    Attached is the entire project provided by @KayKuo in the following forum discussion with @fernandopV2 : https://forums.xamarin.com/discussion/comment/347010#Comment_347010

    Thanks but this solution shows keyboard, then hides it. I am looking for solution to not show it at all when custom Entry receives the focus. Showing it then hiding it based on entry makes things even worse.

  • igorkr_10igorkr_10 Member ✭✭✭
    edited February 19

    I am using this code for disabling keyboard and raising Tapped event. Maybe it will be useful for you.
    In Forms declare your Entry (RoundedEntry in my case)

    public class RoundedEntry : Entry
        {            
            public static readonly BindableProperty FocusableProperty = BindableProperty.Create(nameof(Focusable), typeof(bool), typeof(RoundedEntry), true, BindingMode.TwoWay);
    
            public bool Focusable
            {
                get { return (bool)GetValue(FocusableProperty); }
                set { SetValue(FocusableProperty, value); }
            }
    
            public static readonly BindableProperty TappedCommandProperty = BindableProperty.Create(nameof(TappedCommand), typeof(Command),
                typeof(ContainerControl), null, BindingMode.OneWay);
    
            public Command TappedCommand
            {
                get { return (Command)GetValue(TappedCommandProperty); }
                set { SetValue(TappedCommandProperty, value); }
            }
    
            public event EventHandler<EventArgs> Tapped;
    
            public RoundedEntry() : base()
            {            
            }
    
            public void TappedInvoke()
            {
                if (this.TappedCommand != null && this.TappedCommand.CanExecute(null))
                {
                    this.TappedCommand?.Execute(null);
                }
                this.Tapped?.Invoke(this, new EventArgs());
            }
      }
    

    Then add renderer (I have for android only for now)

    public class RoundedEntryRenderer : EntryRenderer
    {
        public new RoundedEntry Element { get { return base.Element as RoundedEntry; } }
    
        public RoundedEntryRenderer(Context context) : base(context)
        {
    
        }
    
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
            RoundedEntry roundedEntry = e.NewElement as RoundedEntry;
            if (this.Control != null && roundedEntry != null)
            {                
                this.SetIsFocusable();
            }
        }
    
        private void OnClick(object sender, EventArgs e)
        {
            this.Element.TappedInvoke();
        }
    
        private void SetIsFocusable()
        {
            if (this.Control == null) return;
            this.Control.Focusable = this.Element.Focusable;
            if (this.Element.Focusable)
            {
                this.Control.Click -= this.OnClick;
            }
            else
            {
                this.Control.InputType = InputTypes.Null;
                this.Control.Click += this.OnClick;
            }
        }
    
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);            
            if (e.PropertyName == "Focusable")
            {
                this.SetIsFocusable();
            }
        }
    }
    
Sign In or Register to comment.