问题
The problem occurs on Android.
I have implemented a custom renderer for a WebView
to get the capability of resizing the height request base on its content.
I took this from a xamarin forum post.
[assembly: ExportRenderer(typeof(AutoHeightWebView), typeof(AutoHeightWebViewRenderer))]
namespace MyProject.Droid.Renderers
{
public class AutoHeightWebViewRenderer : WebViewRenderer
{
public AutoHeightWebViewRenderer(Context context): base(context) {}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
if (e.NewElement is AutoHeightWebView webViewControl)
{
if (e.OldElement == null)
{
Control.SetWebViewClient(new ExtendedWebViewClient(webViewControl));
}
}
}
class ExtendedWebViewClient : Android.Webkit.WebViewClient
{
private readonly AutoHeightWebView _control;
public ExtendedWebViewClient(AutoHeightWebView control)
{
_control = control;
}
public override async void OnPageFinished(Android.Webkit.WebView view, string url)
{
if (_control != null)
{
int i = 10;
while (view.ContentHeight == 0 && i-- > 0) // wait here till content is rendered
{
await System.Threading.Tasks.Task.Delay(100);
}
_control.HeightRequest = view.ContentHeight;
}
base.OnPageFinished(view, url);
}
}
}
}
Based on a certain logic, I change the source of the WebView
and use the custom renderer to resize the view.
This works when the size is increased but not when the content size is smaller than the one before...
The be clearer, if I set the source of the WebView
to a html file that is 200px height and change it to a html file that is 1000px, it works fine and I can see all the content. BUT, if I try to go back to my 200px html file, I get a 800px blank space underneath since the content doesn't change on the view.ContentHeight
and keep the value of 1000px.
I followed this issue/thread and didn't find a solution to resolve this problem : https://github.com/xamarin/Xamarin.Forms/issues/1711
I have seen a lot of topics on Android saying that we need to recreate the webview. Is there any other solution?
回答1:
I found a way to do it based on this thread.
I first tried with a JS command that returns the body height : document.body.scrollHeight
.
The problem was the same, it always returned the largest size, but never decreased the size.
As the JS command have no problem to increase the size, I had to set the height to 0, set a 100ms delay (arbitrary) and then get the height of the HTML with the JS command above and set the HeightRequest
of the view.
With this, the HTML body height will not decrease... It will always start from 0 and increase to the HTML body size.
Final result :
public class AutoHeightWebViewRenderer : WebViewRenderer
{
static AutoHeightWebView _xwebView = null;
public AutoHeightWebViewRenderer(Android.Content.Context context) : base(context)
{
}
class DynamicSizeWebViewClient : WebViewClient
{
public async override void OnPageFinished(Android.Webkit.WebView view, string url)
{
try
{
if (_xwebView != null)
{
view.Settings.JavaScriptEnabled = true;
view.Settings.DomStorageEnabled = true;
_xwebView.HeightRequest = 0d;
await Task.Delay(100);
string result = await _xwebView.EvaluateJavaScriptAsync("(function(){return document.body.scrollHeight;})()");
_xwebView.HeightRequest = Convert.ToDouble(result);
}
base.OnPageFinished(view, url);
}
catch (Exception ex)
{
Console.WriteLine($"{ex.Message}");
}
}
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
_xwebView = e.NewElement as AutoHeightWebView;
if (e.OldElement == null)
{
Control.SetWebViewClient(new DynamicSizeWebViewClient());
}
}
}
来源:https://stackoverflow.com/questions/60399897/how-to-update-custom-webview-height-request-when-content-is-shrunk