question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Android] When a user taps off of an input control the keyboard no longer closes

See original GitHub issue

Description

Copied from https://github.com/dotnet/maui/issues/6933#issuecomment-1236381789

In XF when you click/tapped outside of a focused entry the entry would lose focus and the keyboard would close. This behavior wasn’t copied over to MAUI because the implementation on XF was very wrong and broke accessibility.

If we decide to “fix” this for MAUI .NET 7 we should not implement the “Unfocus” behavior and only make it so that it closes the keyboard.

Reasons to fix

  • this is how it works in Forms
  • we already have code for iOS that’s custom that does this so it’s compelling to do this in Forms so we can match behavior for users migrating.
  • we can make it work in a way that doesn’t break accessibility like it did in XF
  • We can make the behavior match Forms in NET7 and then provide an API in NET8 that lets users toggle this behavior on/off for iOS and Android
  • Users currently don’t have an easy way to enable this behavior so as to match with XF. At a later point we might have enough API surface for users to do this themselves easily but currently they do not.

Reasons not to fix for .NET 7

  • This is not a standard feature of the platform and anytime we modify the platform behavior that will typically have consequences that we aren’t even aware of.
  • We can leave the behavior how this is for now in NET7 and provide an API in NET8 that lets users toggle this behavior on/off for iOS and Android
  • By default on iOS/Android if an input field has focus and then you click on a button the keyboard will not close. This is the desired behavior in a lot of scenarios (think chat app). If we add this behavior back into .NET 7 this will change the current behavior on Android so it might be better to wait until we can implement https://github.com/dotnet/maui/issues/12003

Concerns

The way this behavior worked in XF was to make the entire page clickable which made apps completely inaccessible. Anybody wanting to pass WCAG certification with an XF app were forced to write custom code to disable this behavior. The only place where I’ve seen this behavior is if the area you click off to is interactable in some format. For example, the maps app if you click off to the results but if you test with the WIFI app or contacts app they don’t work like this. If you want to add this behavior yourself I think this would be the best way to go about it https://stackoverflow.com/a/28939113 so you don’t confuse TalkBack.

I think we need to flesh out the use cases here a bit more so we can provide guidance or additional APIs to give people the ability to make these choices if they want to but we’re not going to make this the default behavior unless provided some examples that are accessible and preferable over the default Android behavior or if it can demonstrated that .NET MAUI breaks Android platform defaults.

Steps to Reproduce

  • click on an entry
  • click off the entry
  • keyboard is still open

Link to public reproduction project repository

N/A

Version with bug

6.0 Release Candidate 2 or older

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android

Did you find any workaround?

Relevant log output

No response

Issue Analytics

  • State:open
  • Created 9 months ago
  • Reactions:5
  • Comments:18 (6 by maintainers)

github_iconTop GitHub Comments

4reactions
taz4270commented, Dec 29, 2022
public class MainActivity : MauiAppCompatActivity
{
public override bool DispatchTouchEvent(MotionEvent e)
    {
        if (e.Action == MotionEventActions.Down)
        {
            var view = CurrentFocus;
            if (view is EditText editText)
            {
                editText.ClearFocus();
                InputMethodManager imm = (InputMethodManager)GetSystemService(Context.InputMethodService);
                imm.HideSoftInputFromWindow(view.WindowToken, 0);
            }
        }

        return base.DispatchTouchEvent(e);
    }
}

Android is currently using it temporarily. I hope it will be revised as soon as possible.

I make one solution based on this one but without keyboard flicker everytime you repress it

public class MainActivity : MauiAppCompatActivity, IOnTouchListener
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            Window.DecorView.ViewTreeObserver.GlobalFocusChange += FocusChanged;
        }

        void FocusChanged(object sender, ViewTreeObserver.GlobalFocusChangeEventArgs e)
        {
            if (e.OldFocus is not null)
            {
                e.OldFocus.SetOnTouchListener(null);
            }

            if (e.NewFocus is not null)
            {
                e.NewFocus.SetOnTouchListener(this);
            }


            if (e.NewFocus is null && e.OldFocus is not null)
            {
                InputMethodManager imm = InputMethodManager.FromContext(this);

                IBinder wt = e.OldFocus.WindowToken;

                if (imm is null || wt is null)
                    return;

                imm.HideSoftInputFromWindow(wt, HideSoftInputFlags.None);
            }
        }

        public override bool DispatchTouchEvent(MotionEvent ev)
        {
            bool dispatch = base.DispatchTouchEvent(ev);

            if (ev.Action == MotionEventActions.Down && CurrentFocus is not null)
            {
                if (!KeepFocus)
                    CurrentFocus.ClearFocus();
                KeepFocus = false;
            }

            return dispatch;
        }

        bool KeepFocus { get; set; }

        bool OnTouch(View v, MotionEvent e)
        {

            if (e.Action == MotionEventActions.Down && CurrentFocus == v)
                KeepFocus = true;

            return v.OnTouchEvent(e);
        }

        bool IOnTouchListener.OnTouch(View v, MotionEvent e) => OnTouch(v, e);
    }

The explanation is simple, if focused it will set the touch listener on receiving the touch it changed the flag KeepFocus to true

If KeepFocus is not set, the dispatch touch will unfocus If Unfocus the keyboard hides

There is still an issue which is if you touch another entry, it will still flicker but every other instance it working fine, might need to tune somthing to make it work at 100%

Hope I could be of some use

1reaction
PureWeencommented, Dec 30, 2022

I’ve put together a behavior here that seems to work alright and cover most cases. T

https://github.com/PureWeen/ShanedlerSamples/tree/main/ShanedlerSamples/Library

<Entry Placeholder="Text Field" Text="Starting text" WidthRequest="300">
                <Entry.Behaviors>
                    <local:TapToCloseBehavior></local:TapToCloseBehavior>
                </Entry.Behaviors>

            </Entry>
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureShanedler()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });

        return builder.Build();
    } 
  • This lets you opt in some fields but not all fields.
  • Handles cases where you re-tap on the same entry and it won’t close the keyboard
  • Covers cases where the keyboard might flicker.
  • Also handles if the user scrolls. So, if the user scrolls the screen instead of taps the screen than it doesn’t close the keyboard.

Some version of this will probably make it into the keyboard

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to hide soft keyboard on android after clicking outside ...
This code is simple, but it has an obvious issue: it closes the keyboard when anywhere is touched. That is if you tap...
Read more >
Handle input method visibility
When input focus moves in or out of an editable text field, Android shows or hides the input —such as the on-screen keyboard—as...
Read more >
How do I avoid the Android keyboard closing “randomly ...
Go to your device's "Settings" app. Scroll down to the "System" section and tap on "Languages & input." In the "Keyboards & input...
Read more >
Keep mobile keyboard open
At the moment, Unity automatically closes the keyboard if a user touches outside of the keyboard area or if the user submits the...
Read more >
Fix problems with Gboard - Android
On your Android phone or tablet, open the Settings app Settings app . ; Tap System and then Languages and input. ; Tap...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found