【问题标题】:How to update custom WebView height request when content is shrunk内容缩小时如何更新自定义 WebView 高度请求
【发布时间】:2020-03-11 01:02:28
【问题描述】:

问题出现在 Android 上。

我已经为 WebView 实现了一个自定义渲染器,以便能够根据其内容调整高度请求的大小。

这是我从一个 xamarin 论坛帖子中获取的。

[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);
            }
        }
    }
}

基于一定的逻辑,我更改了WebView的来源,并使用自定义渲染器来调整视图大小。

这在大小增加时有效,但在内容大小小于之前的大小时无效...

更清楚一点,如果我将WebView 的源设置为 200px 高度的 html 文件并将其更改为 1000px 的 html 文件,它工作正常,我可以看到所有内容。但是,如果我尝试返回我的 200px html 文件,我会在下面得到一个 800px 的空白空间,因为 view.ContentHeight 上的内容不会改变并保持 1000px 的值。

我关注了这个问题/线程并没有找到解决这个问题的解决方案:https://github.com/xamarin/Xamarin.Forms/issues/1711

我在Android上看到很多话题说我们需要重新创建webview。还有其他解决办法吗?

【问题讨论】:

  • 您是否尝试将常规WebView 包裹在Grid 中,并将RowDefinition 设置为Auto
  • 是的,我必须手动调整高度,否则我看不到内容。如果我没记错的话,内容是在视图渲染之后出现的,所以很可能是因为文件没有加载,所以高度设置为0。
  • 尝试设置 WebView 的 IsVisible = false,然后再设置回 true。延迟后可能需要在 UI 线程上执行第二组 (=true)。 Hacky,但它是重新创建 webview 的替代方法。
  • @ChristopherSt-Pierre 我可以根据你的代码重现你的问题,我建议你可以invoke C# from JavaScript获取内容高度,你可以看看:forums.xamarin.com/discussion/160787/…

标签: android xamarin xamarin.forms webview xamarin.android


【解决方案1】:

我找到了一种基于this thread的方法。

我首先尝试使用返回身体高度的 JS 命令:document.body.scrollHeight。 问题是一样的,它总是返回最大的尺寸,但从来没有减小尺寸。

由于JS命令增加大小没有问题,我只好将高度设置为0,设置100ms延迟(任意)然后用上面的JS命令获取HTML的高度并设置HeightRequest视图。

这样,HTML body 的高度就不会减少了……它总是从 0 开始,一直增加到 HTML body 的大小。

最终结果:

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());
        }
    }
} 

【讨论】:

    猜你喜欢
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-30
    • 2012-09-14
    • 1970-01-01
    相关资源
    最近更新 更多