dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
21.99k stars 1.72k forks source link

Soft Keyboard Dismiss issues on Android #19514

Open DawidBester opened 9 months ago

DawidBester commented 9 months ago

Description

I'm migrating an app from Xamarin Forms to NET8/MAUI and on Android the soft keyboard dismiss no longer works as expected. Soft keyboard dismiss on iOS seems to work as expected.

In the sample project, there's three keyboard dismiss test scenarios:

Test 1: An Entry Control on a ContentPage

Test 2: An Entry control in an Expander;

Test 3: Programmatically setting the Focus on the Entry Control, add text, delay execution, then set Entry Unfocus.

image

Steps to Reproduce

Run sample code:

Test 1: Enter text into Entry;

Test 2: Enter text into Entry wrapped inside an Expander;

Test 3: Setting Entry Focus and Unfocus in button click event code to popup and then dismiss soft keyboard

private async void Button_OnClicked(object? sender, EventArgs e)
{
    Test3Entry.Focus();
    Test3Entry.Text = "Keyboard Focus set";
    await Task.Delay(TimeSpan.FromSeconds(1));
    Test3Entry.Unfocus();
}

Link to public reproduction project repository

https://github.com/DawidBester/SoftKeyboardDismissTest

Version with bug

8.0.3

Is this a regression from previous behavior?

Yes, this used to work in Xamarin.Forms

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android emulator API 33

Did you find any workaround?

Did not find a workaround

Relevant log output

No response

PureWeen commented 8 months ago

1) good to hear 2) I think this might be an issue with the expander control itself. My guess here is that the expander control isn't correctly wiring up the logical children so the visual tree isn't properly represented in code. If MCT can fix the exapnder to add the children elements as logical children then this should start to work. 3) You can't really completely unfocus something in Android or WinUI. For example, WinUI doesn't even have an "Unfocus" API, we do some awkward hack in the code to relieve focus from an entry and then focus will always just go to the first element in the interaction chain. iOS lets you "unfocus" but it works a little different than android. iOS generally handles the idea that nothing has visual focus while the keyboard is closed "better" than android and iOS.

ghost commented 8 months ago

Hi @DawidBester. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

DawidBester commented 8 months ago

@PureWeen Thanks for reviewing the issue and the additional info.

Item 2. I've tested the Syncfusion SfExpander control and the keyboard is dismissed as expected, so will use the Syncfusion expander component as the workaround.

This might be the same issue as the MCT Expander control. I've had a look at the docs, and referencing your recommendation, I cant figure out how to add the children elements as logical children in the control which was migrated from XF.

Test 4 detail:

The soft keyboard is not dismissed when using a button on a custom control to do back navigation of a page.
The custom control displays a header at the top of each app page with navigation buttons on the left and right.

Custom control used as follows:

 <controls:PageHeader
     x:Name="PageHeader"
     Grid.Row="0"
     BindingContext="{x:Reference Test4ContentPage}"
     LeftButtonIcon="&lt;"
     LeftButtonIconText="Back"
     LeftButtonTappedCommand="{Binding LeftButtonCommand}"
     PageTitleText="Test 4 Page" />

I've updated the reproduction project repository and added with Test 4 and Test5, see: https://github.com/DawidBester/SoftKeyboardDismissTest

Test 4 steps:

image

image

image

Test 5: On the Test4Page I've also added a button labelled "Test 5: Bypass Custom Control to Navigate Back", which bypasses the control, and the software keyboard is dismissed as expected.

private void ButtonNavigation_OnClicked(object? sender, EventArgs e)
 {
     Navigation.PushAsync(new Test4Page());
 }
ninachen03 commented 5 months ago

Verified this issue with Visual Studio 17.10.0 Preview 3 (8.0.14 & 8.0.0-rc.2.9530). Can repro it with sample project

DawidBester commented 5 months ago

I've updated the sample project to the latest available packages in the hope that some items have been fixed, but all issues still exist.

The keyboard not being dismissed results in a bad and confusing user experience and is blocking app migration from XF to MAUI.

Latest packages used:

<PackageReference Include="CommunityToolkit.Maui" Version="8.0.1" />
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.40-nightly.10467" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.40-nightly.10467" />
DawidBester commented 4 months ago

Finally stumbled onto a workaround:

Add an OnUnfocused event handler to each Entry and use the CommunityToolkit KeyboardExtensions to dismiss the softkeyboard in code behind.

 <Entry x:Name="Test4Entry" 
        Unfocused="Test4Entry_OnUnfocused"
     BackgroundColor="LightGoldenrodYellow"
     Placeholder="Enter Something"
     TextColor="Black" />
private void Test4Entry_OnUnfocused(object? sender, FocusEventArgs e)
{
    DismissEntryKeyboard(sender);
}

public async void DismissEntryKeyboard(object? sender)
{
    if (sender is ITextInput textInput)
    {
        Debug.WriteLine("Test4Entry_OnUnfocused");
        await textInput.HideKeyboardAsync(CancellationToken.None);
    }
}

Workaround References https://stackoverflow.com/questions/73199602/need-a-way-to-hide-soft-keyboard-in-mauis-editor-entry-fields