Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maui BlazorWebView input covered by Keyboard #14197

Closed
radderz opened this issue Mar 25, 2023 · 16 comments
Closed

Maui BlazorWebView input covered by Keyboard #14197

radderz opened this issue Mar 25, 2023 · 16 comments
Labels
area-blazor Blazor Hybrid / Desktop, BlazorWebView p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/android 🤖 platform/iOS 🍎 s/triaged Issue has been reviewed s/try-latest-version Please try to reproduce the potential issue on the latest public version t/bug Something isn't working
Milestone

Comments

@radderz
Copy link

radderz commented Mar 25, 2023

Description

When you have an input near the bottom of your page, on click of an input, the soft keyboard will cover the input.

There is no simple way to deal with this in MAUI with Blazor. Ideally it would either pan the whole view up or add a translation of the view based on the size of the soft keyboard and scroll to the input. Adding margin on the Blazor view could work but then the height of the view would be affected causing full browser redrawing of the page which wouldn't be ideal.

The issue lies in that the website itself is scrollable, and can have elements at the bottom of the page, but the keyboard is just overlapping the bottom section of the screen and the bottom of the web view is covered.

Steps to Reproduce

  1. Create standard Maui.NET Blazor app
  2. Add a many inputs into the index.razor till it extends beyond the page (i.e. make it scroll or be right at the bottom of the screen).
  3. Click on the last input at the bottom of the page, and see that soft keyboard obstructs visibility to the input.

Link to public reproduction project repository

Don't have one

Version with bug

7.0 (current)

Last version that worked well

Unknown/Other

Affected platforms

iOS, Android

Affected platform versions

iOS 14+, Android 24+

Did you find any workaround?

#14197 (comment)

Not yet, I am going to try to translate the webview by the size of the keyboard to see if that works well, but this may not be perfect either (This would be similar to the Android specific PAN feature). But to do this it needs to be easy to access when the keyboard is visible or not.

The Android specific PAN feature also doesn't work, I am guessing this is due to the input not being a native component.

Relevant log output

No response

@radderz radderz added the t/bug Something isn't working label Mar 25, 2023
@radderz
Copy link
Author

radderz commented Mar 25, 2023

For now I am doing this,

I find that iOS and Android both react the same way, where they resize the Content Page to the remainder of the screen, if this is sufficient for your issue you can do the below. iOS does this by default and Android by default seems to do nothing or maybe does the pan option (which doesn't work if the item is at the bottom of the scroll view.


using Microsoft.Maui.Controls.PlatformConfiguration.AndroidSpecific;
using Application = Microsoft.Maui.Controls.Application;

namespace SoftKeyboardBug;

public partial class App : Application
{
	public App()
	{
		InitializeComponent();

		MainPage = new MainPage();

        Current.On<Microsoft.Maui.Controls.PlatformConfiguration.Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);
    }
}

This means that it'll trigger a full resize on the view since the container is changing in size, this can sometimes be ok, but we would prefer to be able to choose the Pan equivalent (which doesn't seem to work in android for Maui.NET Blazor web views.) and have the same equivalent in iOS so the view doesn't change and just gets translated.

@radderz
Copy link
Author

radderz commented Mar 25, 2023

To give a better reason as to why the translation version would be beneficial.

If you have a 100% height layout instead of a scrollable layout, this could break the web layout that was fine prior to the keyboard being visible.

@jsuarezruiz jsuarezruiz added the area-blazor Blazor Hybrid / Desktop, BlazorWebView label Mar 27, 2023
@danroth27 danroth27 added this to the .NET 8 Planning milestone Mar 27, 2023
@datvm
Copy link

datvm commented Mar 28, 2023

Can confirm your workaround works. Is this a planned fix as a default behavior in .NET 8?

@TomDacquinDMS
Copy link

The provided fix doesn't provide a solution for my project (.NET 7, Android, MAUI BLAZOR project)
Any other suggestions?

@KieranDevvs
Copy link

This is a massive issue, the virtual keyboard wipes out half of the UI with no way for the user to access it.
If there is a text field at the bottom of the UI and the user focuses on the control, you can type but you cant see the text field or the text that has been written.

@Yu-Core
Copy link

Yu-Core commented May 5, 2023

I am using a method ( .NET 7 )
It was originally a piece of Java code, but I changed it to C#.

  • First
    Add WebViewSoftInputPatch.cs to the Platforms/Android folder, pay attention to using, and not one should be missing. Don't forget to change the namespace too
using Android.Content.Res;
using Android.Views;
using Android.Widget;
using System.Runtime.Versioning;
using static Android.Resource;
using Activity = Android.App.Activity;
using Rect = Android.Graphics.Rect;
using View = Android.Views.View;

namespace MauiBlazor3.Platform.Android;

[SupportedOSPlatform("Android")]
public static class WebViewSoftInputPatch
{
    static Activity Activity => Microsoft.Maui.ApplicationModel.Platform.CurrentActivity ?? throw new InvalidOperationException("Android Activity can't be null.");
    static View MChildOfContent;
    static FrameLayout.LayoutParams FrameLayoutParams;
    static int UsableHeightPrevious = 0;

    public static void Initialize()
    {
        FrameLayout content = (FrameLayout)Activity.FindViewById(Id.Content);
        MChildOfContent = content.GetChildAt(0);
        MChildOfContent.ViewTreeObserver.GlobalLayout += (s, o) => PossiblyResizeChildOfContent();
        FrameLayoutParams = (FrameLayout.LayoutParams)MChildOfContent?.LayoutParameters;
    }

    static void PossiblyResizeChildOfContent()
    {
        int usableHeightNow = ComputeUsableHeight();
        if (usableHeightNow != UsableHeightPrevious)
        {
            int usableHeightSansKeyboard = MChildOfContent.RootView.Height;
            int heightDifference = usableHeightSansKeyboard - usableHeightNow;
            if (heightDifference < 0)
            {
                usableHeightSansKeyboard = MChildOfContent.RootView.Width;
                heightDifference = usableHeightSansKeyboard - usableHeightNow;
            }

            if (heightDifference > usableHeightSansKeyboard / 4)
            {
                FrameLayoutParams.Height = usableHeightSansKeyboard - heightDifference;
            }
            else
            {
                FrameLayoutParams.Height = usableHeightNow;
            }
        }

        MChildOfContent.RequestLayout();
        UsableHeightPrevious = usableHeightNow;
    }

    static int ComputeUsableHeight()
    {
        Rect rect = new Rect();
        MChildOfContent.GetWindowVisibleDisplayFrame(rect);
        if (IsImmersiveMode())
        {
            return rect.Bottom;
        }
        else
        {
            return rect.Bottom - GetStatusBarHeight();
        }
    }

    static int GetStatusBarHeight()
    {
        int result = 0;
        Resources resources = Activity.Resources;
        int resourceId = resources.GetIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0)
        {
            result = resources.GetDimensionPixelSize(resourceId);
        }
        return result;
    }

    static bool IsImmersiveMode()
    {
        View decorView = Activity.Window.DecorView;
        int uiOptions = (int)decorView.SystemUiVisibility;
        return (uiOptions & (int)SystemUiFlags.Immersive) == (int)SystemUiFlags.Immersive;
    }
}



  • Second
    Add the following code to Platforms/Android/MainActivity.cs
protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        WebViewSoftInputPatch.Initialize();
    }

Please note:

Compared to the initial answer, I have made some modifications. Mainly to solve problems that may occur in small window mode and full screen mode

@KieranDevvs
Copy link

I can confirm @Yu-Core's solution does the job. I would still like to see this as default MAUI behaviour though.

@SKIDDOW
Copy link

SKIDDOW commented Jun 7, 2023

Yes @Yu-Core's solution works. ❤️

@samhouts samhouts added the p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint label Jun 8, 2023
@oalabbasi
Copy link

Thank you @Yu-Core your soultion working well :)
#14197 (comment)

@Redth
Copy link
Member

Redth commented Jul 12, 2023

@PureWeen @tj-devel709 any thoughts on this one after having done some of the keyboard work recently?

@samhouts samhouts modified the milestones: .NET 8 Planning, .NET 8 GA Jul 12, 2023
@oalabbasi
Copy link

oalabbasi commented Jul 12, 2023 via email

@Kebechet
Copy link

Kebechet commented Aug 7, 2023

hopefully this will be shipper in .NET 8

@Zhanglirong-Winnie Zhanglirong-Winnie added s/triaged Issue has been reviewed s/try-latest-version Please try to reproduce the potential issue on the latest public version labels Aug 11, 2023
@ghost
Copy link

ghost commented Aug 11, 2023

Hi @radderz. We have added the "s/try-latest-version" label to this issue, which indicates that we'd like you to try and reproduce this issue on the latest available public version. This can happen because we think that this issue was fixed in a version that has just been released, or the information provided by you indicates that you might be working with an older version.

You can install the latest version by installing the latest Visual Studio (Preview) with the .NET MAUI workload installed. If the issue still persists, please let us know with any additional details and ideally a reproduction project provided through a GitHub repository.

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.

@Zhanglirong-Winnie
Copy link

Verified this issue with Visual Studio Enterprise 17.7.0 Preview 6.0. Not repro on android platform.
image

@ghost ghost closed this as completed Aug 18, 2023
@github-project-automation github-project-automation bot moved this from Todo to Done in MAUI SDK Ongoing Aug 18, 2023
@bharathwajv
Copy link

bharathwajv commented Sep 13, 2023

#14197 (comment)

Works Great! but IsImmersiveMode method fails.

@ghost
Copy link

ghost commented Sep 13, 2023

Hello lovely human, thank you for your comment on this issue. Because this issue has been closed for a period of time, please strongly consider opening a new issue linking to this issue instead to ensure better visibility of your comment. Thank you!

@ghost ghost locked as resolved and limited conversation to collaborators Oct 14, 2023
This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-blazor Blazor Hybrid / Desktop, BlazorWebView p/1 Work that is important, and has been scheduled for release in this or an upcoming sprint platform/android 🤖 platform/iOS 🍎 s/triaged Issue has been reviewed s/try-latest-version Please try to reproduce the potential issue on the latest public version t/bug Something isn't working
Projects
None yet
Development

No branches or pull requests