maui
maui copied to clipboard
WebView Flickers on Android when you visit the page more than once
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
- download the repo
- run it on android.
- Click the button to go to the webview page and then click back button
- 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
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.
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
@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
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
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 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?
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.
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 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?
@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);
}