Entry.Focus() Not Working For Android

attyranattyran USMember ✭✭
edited July 2017 in Xamarin.Forms

Hello,

Currently, I am using this setup to set focus to an Entry:

protected override void OnAppearing()
{
    base.OnAppearing();

    Entry emailEntry = this.FindByName<Entry>("emailEntry");
    emailEntry.Focus();
}

The Entry is part of a StackLayout. So on the iOS emulator it focuses on the entry and brings up a keyboard. On the Android emulator, however, it just sets focus to the entry, but does not bring up the keyboard. I've noticed other people having the same issues in the forums, but couldn't find an answer or workaround. Are there currently any plans to fix this, and what is a workaround I can use?

Thanks

Best Answer

Answers

  • attyranattyran USMember ✭✭

    Thanks, John. Yes, it is only for the first page, and I've added myself to the cc list for that bug. Is there currently a workaround to have the keyboard show up on the first page?

  • JohnHardmanJohnHardman GBUniversity mod

    @AlexTran.8371 - I don't have an Entry on my first page, so cannot answer that without spending time investigating (a job for people who work for Xamarin ;-) ).

    Whilst it is a hack, as a guess at what might work as a workaround (I haven't looked at the Xamarin.Forms source to see what might be causing that bug, so it is a guess), I'd be tempted to try putting a delay before the Focus to see if that makes any difference.

                                await Task.Run(() =>
                                {
                                    Task.Delay(100);
                                    Device.BeginInvokeOnMainThread(async () =>
                                    {
                                        emailEntry.Focus();
                                    });
                                });
    

    And if that doesn't work, I'd then try putting ScrollToAsync (awaited, with ScrollToPosition.End) before the Focus. Getting even more hacky, but without knowing the cause of the bug, it's guesswork based on stuff I have experienced with earlier XF bugs.

  • attyranattyran USMember ✭✭

    Thanks, John. Adding that quick delay did not fix the issue. I'll try looking into some other alternatives.

  • JohnHardmanJohnHardman GBUniversity mod
    edited November 2017

    @LoganEdge - Note that whatever value is used, doing this introduces a race condition (which is why I described it as a hack). Increasing the value just reduces the chance of the focus not being set, but does not eliminate it.

    I still haven't checked the Xamarin.Forms source code to see what is happening, but my guess is that calling Focus() only takes effect if the Entry (or possibly the complete page) has already been rendered. Increasing the delay time increases the chance of rendering having completed.

  • @LoganEdge Thankyou :smile: it works for me.

  • AndyHuntsmanAndyHuntsman USMember ✭✭

    FYI, here's an RX version of what LoganEdge posted above:

    protected override void OnAppearing()
    {
        base.OnAppearing();
    
        Observable
            .Return(true)
            .Delay(TimeSpan.FromMilliseconds(600))
            .SubscribeOn(ViewModel.BackgroundScheduler) // View model defines schedulers from a provider
            .ObserveOn(ViewModel.MainThreadScheduler)
            .Subscribe(_ => this.FindByName<Entry>("MyEntry")?.Focus());
    }
    
  • bergisbergis USMember

    Today I stumbled upon the same issue and delaying the .focus() did not work either.

    I ended up using .Unfocus() and then .Focus() again which seems to work fine:

    txtLotID.Unfocus();
    txtLotID.Focus();
    

    It's not perfect but it's better than introducing a race condition.

  • dinobdinob USUniversity ✭✭✭
    edited June 11

    My Entry is not on the first page and I am still seeing this. I put breakpoints to inspect Entry.IsFocused and it is always False. Calling Entry.Focus() also returns always false and the entry is not hidden. Btw, this is creating an issue for me on UWP but not on Andoid or IOS

  • JohnHardmanJohnHardman GBUniversity mod

    There are different solutions to this depending on the scenario. A completely generic solution that handles all scenarios takes care of unfocusing any control already having the focus, hiding the soft keyboard, scrolling to bring the Entry into control that the focus is going to, waiting for it to be in the native layout, and then setting the focus.

    @dinob - it's unclear what your scenario is. Without that information, try calling this method just before doing the Focus() call. If that doesn't sort it, start a new thread with your scenario described and posting your current code.

        public static async Task WaitForViewToBeInNativeLayout(
            View view,
            int millisecondDelay = 1,
            int maxCycles = 10)
        {
            if (view != null)
            {
                // Note that IsInNativeLayout is currently marked for Xamarin internal use only
                int cycle = 0;
                while ((!view.IsInNativeLayout) && (++cycle <= maxCycles))
                {
                    await Task.Delay(TimeSpan.FromMilliseconds(millisecondDelay));
                }
            }
        }
    
  • dinobdinob USUniversity ✭✭✭
    edited June 14

    @JohnHardman Thanks again John! That did not help resolve the issue but it helped figured out what the issue was. Also, suggestion by @bergis to Unfocus, then Focus did not work for me.

    Here is the explanation what was happening

    The Entry I use is hidden, as we want to scan into it but we dont display scan result, so the Entry has its IsVisible set to False to hide it.

    It turns out, IsVisible behaves differently on UWP. While on Android and iOS, setting IsVisible to false will continue to allow hidden Entry to receive input and focus through call to Focus(), on UWP, this is not the case.

    It is simple to prove:

    1. Create a dummy Xamarin Forms project supporting Android, iOS and UWP
    2. Add an Entry in shared portion of project, set its IsVisible to false to hide it
    3. Add a Button and in its code behind, call var isFocused = MyEntry.Focus(). Put breakpoint on this line
    4. Run on Android and IOS, tap on the Button and inspect value of isFocused once the line above executes. It will be True meaning Focus was successful
    5. Run on UWP, tap on the Button and inspect value of isFocused once the line above executes. It will be False meaning Focus failed

    This explains why same code we have is executing fine on Android and iOS but not on UWP.

    Created ticket for this at https://github.com/xamarin/Xamarin.Forms/issues/6536

    Thanks for your help.

  • JohnHardmanJohnHardman GBUniversity mod

    @dinob said:
    It turns out, IsVisible behaves differently on UWP. While on Android and iOS, setting IsVisible to false will continue to allow hidden Entry to receive input and focus through call to Focus(), on UWP, this is not the case.

    I wouldn't be surprised if that was a Windows/UWP thing, rather than being a Xamarin.Forms thing.

    I assume that you have to support a scanner that uses a keyboard wedge rather than one with an API that you can interact with? Keyboard wedges are evil things, best avoided if possible.

  • dinobdinob USUniversity ✭✭✭

    @JohnHardman said:

    @dinob said:
    It turns out, IsVisible behaves differently on UWP. While on Android and iOS, setting IsVisible to false will continue to allow hidden Entry to receive input and focus through call to Focus(), on UWP, this is not the case.

    I wouldn't be surprised if that was a Windows/UWP thing, rather than being a Xamarin.Forms thing.

    I assume that you have to support a scanner that uses a keyboard wedge rather than one with an API that you can interact with? Keyboard wedges are evil things, best avoided if possible.

    That is correct, reason being no need to manage SDKs, EMDKs for multiple vendors, no need for platform specific code, no need for MFI certified Apple devices. Any external HID scanner works on any device, these are just few advantages

  • JohnHardmanJohnHardman GBUniversity mod

    @dinob - I haven't done so, but on UWP have you tried having the Entry with IsVisible = true and TabStop = false, but then putting a BoxView over the top of it?

  • dinobdinob USUniversity ✭✭✭
    edited June 17

    @JohnHardman said:
    @dinob - I haven't done so, but on UWP have you tried having the Entry with IsVisible = true and TabStop = false, but then putting a BoxView over the top of it?

    I resolved my issue by making Entry.IsVisible=True and making it 1px large. I guess you suggest BoxView on top to hide it or? Thanks again

  • JohnHardmanJohnHardman GBUniversity mod

    @dinob said:
    I resolved my issue by making Entry.IsVisible=True and making it 1px large.

    I thought of that too, but discounted it, as it doesn't prevent the user from trying to interact with it (although it would be difficult!). Removing it from the tab sequence and putting a BoxView over the top hopefully would prevent user interaction.

  • dinobdinob USUniversity ✭✭✭

    @JohnHardman said:

    @dinob said:
    I resolved my issue by making Entry.IsVisible=True and making it 1px large.

    I thought of that too, but discounted it, as it doesn't prevent the user from trying to interact with it (although it would be difficult!). Removing it from the tab sequence and putting a BoxView over the top hopefully would prevent user interaction.

    Havent thought about TabStop but that makes sense.
    BoxView, not sure, havent tried it either
    Also, above, I meant to say I set Width/Height to 0px, not 1px, just a correction

  • JohnHardmanJohnHardman GBUniversity mod

    @dinob said:
    Also, above, I meant to say I set Width/Height to 0px, not 1px, just a correction

    0 is better (I figure if it causes a problem, it'll be quickly apparent). I know that on recent versions of Android, they changed the handling of zero-sized controls. I would hope that would be transparent to people writing XF apps.

  • dinobdinob USUniversity ✭✭✭
    edited June 18

    @JohnHardman said:

    @dinob said:
    Also, above, I meant to say I set Width/Height to 0px, not 1px, just a correction

    0 is better (I figure if it causes a problem, it'll be quickly apparent). I know that on recent versions of Android, they changed the handling of zero-sized controls. I would hope that would be transparent to people writing XF apps.

    Hmmm, I did not know about that, hope that will not affect but if it does, the size can always be set to 1px. Btw, I think you are refering to IsTabStopproperty. TabStopis I believe old Windows Forms name.

    ... but it turns out having IsTabStop="False" is causing same issue as IsVisible="False", so no, it dies not work unfortunatelly

  • JohnHardmanJohnHardman GBUniversity mod

    @dinob said:

    @JohnHardman said:

    @dinob said:
    Also, above, I meant to say I set Width/Height to 0px, not 1px, just a correction

    0 is better (I figure if it causes a problem, it'll be quickly apparent). I know that on recent versions of Android, they changed the handling of zero-sized controls. I would hope that would be transparent to people writing XF apps.

    Hmmm, I did not know about that, hope that will not affect but if it does, the size can always be set to 1px. Btw, I think you are refering to IsTabStopproperty. TabStopis I believe old Windows Forms name.

    ... but it turns out having IsTabStop="False" is causing same issue as IsVisible="False", so no, it dies not work unfortunatelly

    Yes, I did mean IsTabStop. I'm very surprised that would cause a problem.

  • dinobdinob USUniversity ✭✭✭

    @JohnHardman said:

    @dinob said:
    Also, above, I meant to say I set Width/Height to 0px, not 1px, just a correction

    0 is better (I figure if it causes a problem, it'll be quickly apparent). I know that on recent versions of Android, they changed the handling of zero-sized controls. I would hope that would be transparent to people writing XF apps.

    btw, I cannot find anything re changes about handling 0 sizes in Android?

  • JohnHardmanJohnHardman GBUniversity mod

    @dinob said:
    btw, I cannot find anything re changes about handling 0 sizes in Android?

    I just happened to spot it when searching for something else earlier. Now that I'm looking for it, I cannot find it. If I spot it again, I'll let you know.

  • dinobdinob USUniversity ✭✭✭

    @JohnHardman said:

    @dinob said:
    btw, I cannot find anything re changes about handling 0 sizes in Android?

    I just happened to spot it when searching for something else earlier. Now that I'm looking for it, I cannot find it. If I spot it again, I'll let you know.

    Thanks, ... btw, I tried setting w/h=0 and it does not work on Android, so I reset to 1 which works on Android, iOS and UWP

Sign In or Register to comment.