maui icon indicating copy to clipboard operation
maui copied to clipboard

WebView Flickers on Android when you visit the page more than once

Open Zack-G-I-T opened this issue 1 year ago • 3 comments
trafficstars

Description

The webView appears fine the first time you load a page. But if you click the back button and then advance to the webView page again, the webView will flicker on Android. I have attached a video showing the issue.

If you set the height request then it seems to fix the issue. However we do not know the size of the content we will be showing in the webview so this workaround is not acceptable.

https://github.com/dotnet/maui/assets/144355037/d86ff798-bb74-4a69-aaaf-4852c4187947

Steps to Reproduce

  1. download the repo
  2. run it on android.
  3. Click the button to go to the webview page and then click back button
  4. repeat step 3 and witness the flickering

Link to public reproduction project repository

https://github.com/Zack-G-I-T/WebviewIssue

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

No response

Did you find any workaround?

If you set the height request then it seems to fix the issue. However we do not know the size of the content we will be showing in the webview so this workaround is not acceptable.

Relevant log output

No response

Zack-G-I-T avatar Dec 14 '23 12:12 Zack-G-I-T

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.

ghost avatar Dec 18 '23 15:12 ghost

We are affected too on this one as we are loading 3rd party payment providers that load a html page and in android it flickers.. Its now in the backlog which we all know that the chances to get it fixed are very very slim.. any workaround or handler to handle the jittery or suggestions? many thanks

gabsamples6 avatar Jan 03 '24 14:01 gabsamples6

@davidortinau @Eilon the maui webview is a basic control whose main events and functionalities should just work, I can understand that you cannot fix everything but boy you cannot load an html that flickers in android , how are we supposed to work with it...

Also looking to implement a WebViewHandler , none of the events fire. so no hacky workaround. Last option left is a blazor webview in a mainly xaml solution.. An answer - a glimmer of hope would me a lot - at the moment this is a showstopper to us..

welcome any workarounds . thanks

gabsamples6 avatar Jan 11 '24 17:01 gabsamples6

Verified this on Visual Studio Enterprise 17.9.0 Preview 2(8.0.3). Repro on Android 14.0-API34, not repro on Windows 11, iOS 17.0 and MacCatalyst with below Project: WebViewIssue.zip

XamlTest avatar Jan 16 '24 06:01 XamlTest

Yikes, that doesn't look good. This looks more like it's a problem with the native WebView on Android, so we'll have to try that out and see if we need to file a bug on Android/Chromium.

Eilon avatar Jan 19 '24 19:01 Eilon

@Eilon thanks for looking into this it's causing a lot of grief on our side. If it's an android issue, why does it work fine on Xamarin?

We tried adding a custom webview handler to bypass the issue and set the height request to match the content, but the OnPageFinished method in the client never gets hit. Could that be linked at all?

Zack-G-I-T avatar Jan 20 '24 08:01 Zack-G-I-T

I am also hitting this issue on a regular basis, even on the first load. Setting a fixed height does mitigate the issue, but it's not an acceptable workaround in my situation as the WebView is within a grid and the height is not deterministic.

plequere-ms avatar Feb 15 '24 08:02 plequere-ms

Also looking to implement a WebViewHandler , none of the events fire. so no hacky workaround. Last option left is a blazor webview in a mainly xaml solution.. An answer - a glimmer of hope would me a lot - at the moment this is a showstopper to us..

@gabsamples6 , here's a hacky workaround that I've found. It's pretty ugly, but it does the job. You can put this in your code behind (here, the name of the WebView control is Browser), or alternatively you could use the Navigated event. In any case, the trick is to use JavaScript to determine if the page is done loading and then compute the height of the content.

            // Wait for the WebView to render the HTML content
            string result;

            for (int i = 0; i < 10; i++)
            {
                result = await Browser.EvaluateJavaScriptAsync("document.readyState");
                if (result == "complete")
                    break;

                await Task.Delay(100);
            }

            // Execute JavaScript to get the content height
            result = await Browser.EvaluateJavaScriptAsync("document.body.scrollHeight");

            if (double.TryParse(result, out double height))
            {
                // Set the WebView height to match its content
                Browser.HeightRequest = height;
            }

plequere-ms avatar Feb 16 '24 08:02 plequere-ms

@plequere-ms that works a treat actually, thanks! the only problem we have and not sure you are getting the same is that if we go back a page and reload the page where the webview is shown we get some weird flickers too like you see in the video at the top of the issue. Do you get the same if you go back a page and then reload the page?

gabsamples6 avatar Feb 16 '24 12:02 gabsamples6

@plequere-ms Thanks a lot for this workaround! You have saved us from a lot of hassle.

This line of code didnt work for me: "result = await Browser.EvaluateJavaScriptAsync("document.readyState");" Maybe because I am just passing a string of html rather than loading a web page.

So instead I made a static class and added a Loaded event to every webview which calls the UpdateHeightDynamically method. This will do the job until MAUI becomes reliable.

   public static class WebViewHelper
   {
        public static async Task UpdateHeightDynamically(object sender)
    {
        var webView = (WebView)sender;
        var updated = await UpdateHeight(webView, 100);
        if (updated) return;
        updated = await UpdateHeight(webView, 500);
        if (updated) return;
        await UpdateHeight(webView,  1000);
    }

    private static async Task<bool> UpdateHeight(WebView webView, int delay)
    {
        await Task.Delay(delay);
        var result = await webView.EvaluateJavaScriptAsync("document.body.scrollHeight");

        if (double.TryParse(result, out double height) && height > 0)
        {
            webView.HeightRequest = height;
            return true;
        }

        return false;
    }
}
    private async void WebView_Loaded(object sender, EventArgs e)
    {
        await WebViewHelper.UpdateHeightDynamically(sender);
    }

Zack-G-I-T avatar Feb 16 '24 15:02 Zack-G-I-T