How to avoid showing keyboard when focusing EntryCell

2»

Posts

  • fernandopV2fernandopV2 Member ✭✭

    Can you share your code to take a look? just the code with the "Enter" logic. Thanks.

  • KayKuoKayKuo Member ✭✭✭

    @fernandopV2
    here is my code,the enter event is automatically called after the scan code is completed.But not working now.
    thank you

  • fernandopV2fernandopV2 Member ✭✭

    But where are you setting the Enter event?

  • KayKuoKayKuo Member ✭✭✭
    edited September 2018

    @fernandopV2 i set it on my entry on xaml, my device will automatically call the enter event after scanning the code, but it is not working now.
    I also set the hidden keyboard before, but it can't be completely disabled. Even if the entry gets the focus, the keyboard will occasionally display. It will only be hidden when I type a string (although this only happens occasionally, but I want it to be completely hide)
    here is my old code .thank you for your patience

  • fernandopV2fernandopV2 Member ✭✭

    I am not sure if I understand your code (also, sorry, I have a lot of time without seeing this code, so I forgot everything).
    I am not calling HideKeyboard on property IsFocused changed.

    I see that my Renderer has been changed since I put it here, so I am attaching it again so you can take a look. Please, check how it is hiding the keyboard now and let me know if you have any question:

    `using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Xamarin.Forms;
    using Android.App;
    using Android.Content;
    using Android.OS;
    using Android.Runtime;
    using Android.Views;
    using Android.Widget;
    using Xamarin.Forms.Platform.Android;
    using Scanpack.net;

    using Android.Graphics;

    using Android.Views.InputMethods;
    using Scanpack.net.Controls;

    [assembly: ExportRenderer(typeof(MyEntry), typeof(Scanpack.net.Android.MyEntryRenderer))]

    namespace Scanpack.net.Android
    {
    public class MyEntryRenderer : EntryRenderer
    {
    // used to keep the original InputType of the component.
    private global::Android.Text.InputTypes inputType;

        // Override the OnElementChanged method so we can tweak this renderer post-initial setup
        protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
        {
            base.OnElementChanged(e);
    
            if (e.OldElement == null)
            {
                var nativeEditText = (global::Android.Widget.EditText)Control;
                nativeEditText.SetSelectAllOnFocus(true);
            }
    
            if (Control != null &&  e.OldElement == null)
            {
               // System.Diagnostics.Debug.WriteLine("Adding EditorAction method");
                // this is a sample: do whatever you want to the textField here!
                //Control.SetBackgroundColor(global::Android.Graphics.Color.DarkGray);
    
                var view = (MyEntry)Element;
                SetFontSize(view);
               //Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
    
                (this.Element as MyEntry).OnHideKeyboard_TriggerRenderer += MyEntryRenderer_HideKeyboard;
                (this.Element as MyEntry).OnFocused_TriggerRenderer += MyEntryRenderer_FocusControl;
    
                inputType = this.Control.InputType; // saves the original inputType.
    
                // link to the property to disable the keyboard if necessary. 
                this.Element.PropertyChanged += (object sender, System.ComponentModel.PropertyChangedEventArgs eve) => {
                    if ( eve.PropertyName == MyEntry.CanShowVirtualKeyboardPropertyName ) {
                        if ( !(this.Element as MyEntry).CanShowVirtualKeyboard ) 
                            this.Control.InputType = 0;
                        else
                            this.Control.InputType = inputType ;
                    }
                };
    
                // if the element is set to not show the keyboard -> disable it (initialization).
                if ( !(this.Element as MyEntry).CanShowVirtualKeyboard ) 
                    this.Control.InputType = 0;
    
    
    
                //this.Control.ShowSoftInputOnFocus = (this.Element as MyEntry).CanShowVirtualKeyboard;
                //System.Diagnostics.Debug.WriteLine("this.Control.ShowSoftInputOnFocus {0}", this.Control.ShowSoftInputOnFocus);
    
                //TODO: (fernandop) Check if this logic to process Enter key is fine, not sure about using ImeAction.ImeNull
                // It looks like it is called twice.
                // Control.ImeOptions = ImeAction.Done;
    
                Control.EditorAction += (sender, args) => {
                    if (args.Event != null)
                    {
                    System.Diagnostics.Debug.WriteLine ("EditorAction {0} - {1}", args.ActionId, args.Event.Action);
                    //* Condition  args.Event.Action == KeyEventActions.Down has been added in order to avoid
                    //* this method to be called twice (on down and on up).
                    if (args.ActionId == ImeAction.ImeNull && args.Event.Action == KeyEventActions.Down) {
                        System.Diagnostics.Debug.WriteLine ("EnterPressed");
                        (this.Element as MyEntry).EnterPressed ();
                    }
                    }
                };
    
            }
    
    
        }
    
        void MyEntryRenderer_HideKeyboard()
        {
            HideKeyboard();
        }
    
        void MyEntryRenderer_FocusControl(object sender, GenericEventArgs<FocusArgs> args)
        {   
            args.EventData.CouldFocusBeSet= this.Control.RequestFocus();
            if (!(this.Element as MyEntry).CanShowVirtualKeyboard)
                HideKeyboard ();
            else
                ShowKeyboard ();
        }
    
    
        public void ShowKeyboard()
        {
            this.Control.RequestFocus();
            InputMethodManager inputMethodManager = this.Control.Context.GetSystemService(Context.InputMethodService) as InputMethodManager;
            inputMethodManager.ShowSoftInput(this.Control, ShowFlags.Forced);
            inputMethodManager.ToggleSoftInput(ShowFlags.Forced, HideSoftInputFlags.ImplicitOnly);
        }
    
        /// <summary>
        /// Hides the soft keyboard.
        /// </summary>
        public void HideKeyboard()
        { 
            //* TODO: This is a workaround so virtual keyboard is not displayed 
            //* doing MyEntry.Focus() shows the keyboard
            //* We need to check if this adds some bug.
            //this.Control.RequestFocus();
            if (!(this.Element as MyEntry).CanShowVirtualKeyboard) {
                //TODO: JoseA. 2015-05-05: I do not think this works correctly. Probably needs to be tested to hide the keyboard on demand. 
                System.Diagnostics.Debug.WriteLine ("HideKeyboard");
                this.Control.InputType = 0; // this probably needs to be commented out. 
                InputMethodManager inputMethodManager = this.Control.Context.GetSystemService (Context.InputMethodService) as InputMethodManager;
                inputMethodManager.HideSoftInputFromWindow (this.Control.WindowToken, HideSoftInputFlags.None); // this probably needs to be set to ToogleSoftInput, forced.
            }// else
                //ShowKeyboard ();
        }
    
        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
    
            var view = (MyEntry)Element;
    
            if (e.PropertyName == "FontSize")
            {
                SetFontSize(view);
            } 
        }
    
        /// <summary>
        /// Sets the font size of the text in MyEntry control.
        /// </summary>
        /// <param name="view">MyEntry view</param>
        private void SetFontSize(MyEntry view)
        {
            Control.SetTextSize(global::Android.Util.ComplexUnitType.Px, view.FontSize);
        } 
    
    
    }
    

    }`

  • KayKuoKayKuo Member ✭✭✭
    edited September 2018

    @fernandopV2 thank you for your help,But I don't quite understand this method.

    Control.EditorAction += (sender, args) => {
                    if (args.Event != null)
                    {
                    System.Diagnostics.Debug.WriteLine ("EditorAction {0} - {1}", args.ActionId, args.Event.Action);
                    //* Condition  args.Event.Action == KeyEventActions.Down has been added in order to avoid
                    //* this method to be called twice (on down and on up).
                    if (args.ActionId == ImeAction.ImeNull && args.Event.Action == KeyEventActions.Down) {
                        System.Diagnostics.Debug.WriteLine ("EnterPressed");
                        (this.Element as MyEntry).EnterPressed ();
                    }
                    }
                };
    

    If I use this code, its enter event will not work.If I don't use this code, the keyboard won't hide

  • fernandopV2fernandopV2 Member ✭✭

    Sorry, I think I should have to include MyEntry.cs class too (In Xamarin forms project). See at the end of this post. Please, tell me if still you find issues, I will create a little project so you can test to see if we find the issue.

    Also, I am using a MyEntry control like this:
    (in xaml.cs)
    txtProdNo.OnFocusChanged += ProdNoFocusChanged;

    txtProdNo.OnEnterPressed += (sender, e) => {
    System.Diagnostics.Debug.WriteLine("txtProdNo.OnEnterPressed - CanAddLines: {0}", ViewModel.CanAddLines);
    txtScannedLabel.FocusAfterDelay (250); // For some reason delay is necessary to set the focus, I remember some issue using Focus();
    };

    private void ProdNoFocusChanged(object sender, EventArgs e)
        {
            Task dummy;
            if (!txtProdNo.IsFocused && txtProdNo.Text != null) {
                txtProdNo.Text = txtProdNo.Text.ToUpper ();
                dummy = ViewModel.GetCartonData (false);
            }
        }
    

    protected override void OnAppearing ()
    {
    base.OnAppearing ();
    if (firstTimeAppearing)
    txtProdNo.Focus();
    firstTimeAppearing = false;
    }

    MyEntry.cs
    `using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using Xamarin.Forms;
    using System.Windows.Input;
    using Scanpack.net.Controls;

    namespace Scanpack.net
    {
    public class FocusArgs
    {
    public bool CouldFocusBeSet { get; set; }
    }

    public class MyEntry: Entry
    {
    
        public static BindableProperty OnEnterPressedCommandProperty = BindableProperty.Create<MyEntry, ICommand>(x => x.OnEnterPressedCommand, null);
    
        public ICommand OnEnterPressedCommand {
            get { return (ICommand)this.GetValue(OnEnterPressedCommandProperty); }
            set { this.SetValue(OnEnterPressedCommandProperty, value); }
        }
    
        /// <summary>
        /// To be used ONLY by the MyEntryRenderer. 
        /// </summary>
        public event Action OnHideKeyboard_TriggerRenderer;
    
        public MyEntry(): base(){
            //CanShowVirtualKeyboard = true; // by default. 
    
            // attaches event handler to make the virtual keyboard disappear. 
            /*this.Focused += (sender, e) => {
                if (!CanShowVirtualKeyboard)
                    HideKeyboard ();
            };*/
    
            this.PropertyChanged += ( sender, e ) => {
                if (e.PropertyName == "IsFocused")  {                
                    FocusChanged();
                }
            };
        }
    
        /// <summary>
        /// Hides the virtual Keyboard. Note: JoseA. 2015-05-05. I think it has a bug.
        /// It is likely it doesn't let the keyboard appear afterwards (disables the keyboard in the component forever).
        /// </summary>
        public void HideKeyboard()
        {
            if (OnHideKeyboard_TriggerRenderer != null)
                OnHideKeyboard_TriggerRenderer();
        }
    
        public event EventHandler OnEnterPressed;
    
        /// <summary>
        /// To be called internally by the component to trigger the EnterPress. 
        /// </summary>
        public void EnterPressed()
        {
            if (OnEnterPressedCommand != null)
                this.OnEnterPressedCommand.Execute (this.OnEnterPressedCommandParameter);
    
            if (OnEnterPressed != null)
                OnEnterPressed(this, EventArgs.Empty);
        }
    
        public event EventHandler OnFocusChanged;
    
        private void FocusChanged()
        {
            if (OnFocusChanged != null)
                OnFocusChanged(this, EventArgs.Empty);
        }
    
        //private bool canVirtualKeyboard; 
        public const string CanShowVirtualKeyboardPropertyName = "CanShowVirtualKeyboard";
        public static readonly BindableProperty CanShowVirtualKeyboardProperty = 
            BindableProperty.Create (CanShowVirtualKeyboardPropertyName, typeof(bool), typeof(MyEntry), true); 
        /// <summary>
        /// Indicates if the virtual keyboard is disabled for this entry. 
        /// </summary>
        /// <value><c>true</c> if this instance is disabled virtual keyboard; otherwise, <c>false</c>.</value>
        public bool CanShowVirtualKeyboard {
            get { return (bool) GetValue(CanShowVirtualKeyboardProperty); }
            set { 
                SetValue (CanShowVirtualKeyboardProperty, value); 
            }
        }
    
        //private bool canVirtualKeyboard; 
        public const string OnEnterPressedCommandParameterPropertyName = "OnEnterPressedCommandParameter";
        public static readonly BindableProperty OnEnterPressedCommandParameterProperty = 
            BindableProperty.Create (OnEnterPressedCommandParameterPropertyName, typeof(string), typeof(MyEntry), ""); 
    
        public string OnEnterPressedCommandParameter {
            get { return (string) GetValue(OnEnterPressedCommandParameterProperty); }
            set { 
                SetValue (OnEnterPressedCommandParameterProperty, value); 
            }
        }
    
        /// <summary>
        /// In order to be able to change the font size.
        /// </summary>
        public static readonly BindableProperty FontSizeProperty =
        BindableProperty.Create("FontSize", typeof(float),
        typeof(MyEntry), 16f);
    
        public float FontSize
        {
            get { return (float)GetValue(FontSizeProperty); }
            set { SetValue(FontSizeProperty, value); }
        }
    
    
        //public event Action OnFocused;
    
        /// <summary>
        /// To be used ONLY by the MyEntryRenderer. 
        /// </summary>
        public event EventHandler<GenericEventArgs<FocusArgs>> OnFocused_TriggerRenderer; 
    
    
        /// <summary>
        /// Necessary sometimes to be able to set the focus after a delay. 
        /// for instance, can't set the focus when the barcode reader is just closing (need to wait).
        /// </summary>
        /// <param name="milliseconds"></param>
        public void FocusAfterDelay(int milliseconds)
        {
          //  http://stackoverflow.com/questions/13740629/how-do-i-trigger-a-method-to-run-after-x-seconds
            var dummyTask = Task.Factory.StartNew(() => Task.Delay(250)).ContinueWith((t) =>
            {
                // it was failing to set the focus sometimes.
                Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
                       Focus()
                       ); 
            }, TaskScheduler.FromCurrentSynchronizationContext());                             
        }
    
        /// <summary>
        /// Attemps to set the focus to it.
        /// </summary>
        /// <returns>True: if it could set the focus.</returns>
        public new bool Focus()
        {
            var args = new GenericEventArgs<FocusArgs>(new FocusArgs { CouldFocusBeSet = false }); 
            // triggers the event in the renderer (so the focus actually changes).
            if (OnFocused_TriggerRenderer != null)
            {                
                OnFocused_TriggerRenderer(this, args);
            }           
    
            /* if (args.EventData.CouldFocusBeSet) // says if it was successful
            {
                // triggers the event in the view... nothing was using this.
                if (OnFocused != null)
                    OnFocused();
            }*/
    
            return args.EventData.CouldFocusBeSet; 
        }
    
    }
    

    }
    `

  • fernandopV2fernandopV2 Member ✭✭

    Also, you will need this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace Scanpack.net.Controls
    {
    ///


    /// To define events with generic data. See: http://stackoverflow.com/questions/3312134/does-net-have-a-built-in-eventargst
    ///

    ///
    public class GenericEventArgs : EventArgs
    {
    public T EventData { get; private set; }

        public GenericEventArgs(T EventData)
        {
            this.EventData = EventData;
        }
    }
    

    }

  • fernandopV2fernandopV2 Member ✭✭

    And mybe this:

    using Scanpack.net.Controls;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace Scanpack.net.Controls
    {
    ///


    /// Utility class to allow fire an async event.
    ///
    /// See: http://stackoverflow.com/questions/27761852/asynchronous-events-in-c-sharp
    ///

    /// Type of data for the event parameter
    public class AsyncEvent
    {
    ///
    /// Call this method to trigger the event.
    ///

    public static async Task OnEvent(
    Func<object, T, Task> handler,
    object sender,
    T eventData)
    {
    if (handler == null)
    {
    return;
    }

            Delegate[] invocationList = handler.GetInvocationList();
            Task[] handlerTasks = new Task[invocationList.Length];
    
            for (int i = 0; i < invocationList.Length; i++)
            {
                handlerTasks[i] = ((Func<object, T, Task>)invocationList[i])(sender, eventData );
            }
    
            await Task.WhenAll(handlerTasks);         
        }
    }
    

    }

  • KayKuoKayKuo Member ✭✭✭

    @fernandopV2 thank you very much :)

  • KayKuoKayKuo Member ✭✭✭
    edited September 2018

    @fernandopV2 sorry,can you share your xaml.cs code complete?I have some errors here. such as pic:

    thank you :)

  • fernandopV2fernandopV2 Member ✭✭

    You can remove the call to GetCartonData since it is a sample, you need to see if your code is entering there.

    Also, firstTimeAppearing is a boolean set to true in the constructor just to perform something OnAppearing the first time it runs.

  • KayKuoKayKuo Member ✭✭✭
    edited September 2018

    @fernandopV2 sorry,Still does not work,As you see,I can type the string normally, but clicking enter does not respond. :'(

    And If I scan the same number, he will append directly instead of overwriting the previous number.

  • fernandopV2fernandopV2 Member ✭✭

    But are you scanning the number and pressing Enter in which keyboard?
    The scanner my client use has a setting to send Enter key after scanning the barcode. How are you sending the Enter key to the Entry control?

  • KayKuoKayKuo Member ✭✭✭
    edited September 2018
    @fernandopV2 yes,There is a setting on my device that will automatically send an enter when I scan the code. But now, there has no enter after scanning the code, so the data of the scan code cannot be stored in the database.
  • fernandopV2fernandopV2 Member ✭✭

    I think I will try to create a little project to see if you can test it in your device.

    How do you attach the command to Enter event? I have this in xaml (OnEnterPressedCommand):

    then in model I have this:

    public ICommand AddScannedLabelCommand { protected set; get; }

    and in model constructor:
    this.AddScannedLabelCommand = new Command((scannedLabel) =>
    {
    if (!String.IsNullOrWhiteSpace(scannedLabel))
    {
    string strScannedLabel = scannedLabel;
    ScannedLabel = ""; // do you have something like this?
    // here you can save strScannedLabel to database.
    }

  • KayKuoKayKuo Member ✭✭✭

    @fernandopV2 You mean, I need to change my original completed method to OnEnterPressedCommand on xamal?
    like Command="{Binding OnEnterPressedCommand}"?

  • fernandopV2fernandopV2 Member ✭✭

    I think so, sorry, the part of xaml code I sent is not appearing in my previous post, here it is:
    <local:MyEntry x:Name="txtScannedLabel" Placeholder="{x:Static local:AppResources.PrintLabelsPlaceHolder}" Text="{Binding ScannedLabel}" OnEnterPressedCommand = "{Binding AddScannedLabelCommand}" OnEnterPressedCommandParameter="{Binding ScannedLabel}" CanShowVirtualKeyboard="{x:Static local:Globals.ShowVirtualKeyboard}" IsEnabled="true" IsVisible="true" />

  • KayKuoKayKuo Member ✭✭✭

    @fernandopV2 thank you,i will test it :)

  • KayKuoKayKuo Member ✭✭✭
    edited September 2018

    @fernandopV2 thank you very much,I can't test on my device right now.,so i test it on Genymotion, I press enter can access the data.
    But there have a problem, When I press enter to save the data, I need to select the data in the entry to input the next data, but SelectAllOnfocus does not work, The data I input will be added based on the first data., instead of overwriting

  • fernandopV2fernandopV2 Member ✭✭

    Why you don't remove the text after saving it? In my app I am doing that so I don't have that issue.
    Also, I think SelectAllOnfocus maybe is failing because the focus is not moving out/in again. You can try using Entry.UnFocus() and then Entry.Focus().
    But I think removing the text should be easier.

  • KayKuoKayKuo Member ✭✭✭

    @fernandopV2 Thank very much,i used Entry.Unfocus to selectAll,I tested successfully on my device.
    I am new for xamarin. This is my first time asking for help on the forum. Thank you for your patience.
    And happy weekend :D

  • fernandopV2fernandopV2 Member ✭✭

    Great! Nice weekend for you too!

  • yjseijasyjseijas Member ✭✭

    HI Guys,

    I´m so sorry, but I'm new in Xamarin. Would you mine to share the complete code of this solution? It's hard to understand and I`m stuck with this issue. I need to develope a scanning barcode label too.

    Thanks!

  • fernandopV2fernandopV2 Member ✭✭

    @yjseijas Can you please wait until next Wednesday? I am very busy preparing an exam. Or maybe @KayKuo can help you, she is a great programmer.

  • yjseijasyjseijas Member ✭✭

    Thanks @fernandopV2, I don`t mine wait untill next wendsday.
    I would appreciate your help.

  • KayKuoKayKuo Member ✭✭✭
    > @yjseijas said:
    > Thanks @fernandopV2, I don`t mine wait untill next wendsday.
    > I would appreciate your help.
    hi what’s your issue? If your problem same to me,maybe I can help you at tomorrow
  • yjseijasyjseijas Member ✭✭

    Hi KayKuo. I´d like to hide the keyboard when an entry control gets the focus. The data entry will be with a scan barcode label. I saw you solved a similar problem. Can you show me how did you do it?

  • KayKuoKayKuo Member ✭✭✭
    @yjseijas Hi,I made a demo that disables the keyboard. I used the code @fernandopV2 provided, but did some processing to make it work for my project. I tested it with the Genymotion it`s worked normal.
    Im using MVVM of prism
  • dinobdinob USUniversity ✭✭✭

    @fernandop Thanks, this is something I also need and will take a look. Much appreciated that you brought it up and kept through

  • yjseijasyjseijas Member ✭✭

    Thanks a lot, KayKou! I´ll be watching it!

  • UweReisewitzUweReisewitz DEMember ✭✭

    Hi,
    I've created a sample with full control over the virtual keyboard and posted it on GitHub:
    https://github.com/UweReisewitz/XamarinAndroidEntry

  • TobyKTobyK GBMember ✭✭✭

    @UweReisewitz Mate, you are a star!!! Finally managed to get rid of the bug in our app of the popping up keyboard on focus and your code works a treat. Ty for sharing, I've found it very useful.

2»
Sign In or Register to comment.