You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Forms PCL项目中WebView自适应内容高度问题求助

解决Xamarin.Forms ListView中WebView自适应内容高度的问题

嘿,我来帮你搞定这个WebView高度自适应的难题!我之前在做类似的帖子展示需求时,也踩过同样的坑,刚好整理了一套可行的方案,分平台给你讲清楚~

第一步:PCL端准备自定义WebView控件

首先我们需要在PCL项目里定义一个继承自WebView的自定义控件,方便后续自定义渲染器识别:

using Xamarin.Forms;

namespace YourProjectNamespace
{
    public class AutoHeightWebView : WebView
    {
        // 自定义绑定属性传递HTML内容,也可以直接用原WebView的Source属性
        public static readonly BindableProperty HtmlContentProperty =
            BindableProperty.Create(nameof(HtmlContent), typeof(string), typeof(AutoHeightWebView), string.Empty);

        public string HtmlContent
        {
            get => (string)GetValue(HtmlContentProperty);
            set => SetValue(HtmlContentProperty, value);
        }
    }
}

然后在ListView的ItemTemplate里使用这个控件,重点要把ListView的HasUnevenRows设为true,让行高自动适配内容:

<ListView x:Name="PostsListView" HasUnevenRows="true">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <local:AutoHeightWebView HtmlContent="{Binding Body}" />
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

注意:拼接HTML时记得加基础样式消除默认边距,避免高度计算不准:

// 给HTML添加基础样式,消除默认边距
var htmlContent = "<html><body style='margin:0;padding:0;'>" + body + "</body></html>";

第二步:Android端自定义渲染器

在Android项目里创建渲染器,监听WebView加载完成事件,通过JS获取内容高度并调整WebView尺寸:

#pragma warning disable CS0618 // 处理API过时警告
using Android.Content;
using Android.Webkit;
using YourProjectNamespace;
using YourProjectNamespace.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(AutoHeightWebView), typeof(AutoHeightWebViewRenderer))]
namespace YourProjectNamespace.Droid
{
    public class AutoHeightWebViewRenderer : WebViewRenderer
    {
        public AutoHeightWebViewRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);

            if (Control != null && e.NewElement != null)
            {
                var autoHeightWebView = e.NewElement as AutoHeightWebView;
                Control.Settings.JavaScriptEnabled = true;
                Control.SetWebViewClient(new CustomWebViewClient(autoHeightWebView));
                Control.LoadDataWithBaseURL(null, autoHeightWebView.HtmlContent, "text/html", "UTF-8", null);
            }
        }

        private class CustomWebViewClient : WebViewClient
        {
            private readonly AutoHeightWebView _webView;

            public CustomWebViewClient(AutoHeightWebView webView)
            {
                _webView = webView;
            }

            public override void OnPageFinished(Android.Webkit.WebView view, string url)
            {
                base.OnPageFinished(view, url);
                // 通过JS获取内容滚动高度
                view.EvaluateJavascript("document.body.scrollHeight;", new JavascriptValueCallback(height =>
                {
                    if (float.TryParse(height, out float contentHeight))
                    {
                        // 转换为Android像素单位,设置WebView高度
                        view.LayoutParameters.Height = (int)(contentHeight * Resources.DisplayMetrics.Density);
                        _webView.HeightRequest = contentHeight;
                        // 通知ListView更新行高
                        ((ListView)_webView.Parent.Parent.Parent).ForceUpdateSize();
                    }
                }));
            }
        }

        private class JavascriptValueCallback : Java.Lang.Object, IValueCallback
        {
            private readonly Action<string> _callback;

            public JavascriptValueCallback(Action<string> callback)
            {
                _callback = callback;
            }

            public void OnReceiveValue(Java.Lang.Object value)
            {
                _callback?.Invoke(value.ToString());
            }
        }
    }
}

第三步:iOS端自定义渲染器

iOS端的处理类似,监听WebView加载完成后获取滚动视图的内容高度:

using Foundation;
using UIKit;
using YourProjectNamespace;
using YourProjectNamespace.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(AutoHeightWebView), typeof(AutoHeightWebViewRenderer))]
namespace YourProjectNamespace.iOS
{
    public class AutoHeightWebViewRenderer : WebViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
        {
            base.OnElementChanged(e);

            if (Control != null && e.NewElement != null)
            {
                var autoHeightWebView = e.NewElement as AutoHeightWebView;
                Control.ScrollView.ScrollEnabled = false; // 禁止内部滚动,让ListView统一处理
                Control.LoadHtmlString(autoHeightWebView.HtmlContent, null);
                Control.LoadFinished += Control_LoadFinished;
            }
        }

        private void Control_LoadFinished(object sender, EventArgs e)
        {
            var webView = sender as UIWebView;
            var autoHeightWebView = Element as AutoHeightWebView;
            if (webView != null && autoHeightWebView != null)
            {
                // 获取内容高度并设置给WebView
                var contentHeight = webView.ScrollView.ContentSize.Height;
                autoHeightWebView.HeightRequest = contentHeight;
                // 通知ListView更新行高
                ((ListView)autoHeightWebView.Parent.Parent.Parent).ForceUpdateSize();
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                Control.LoadFinished -= Control_LoadFinished;
            }
            base.Dispose(disposing);
        }
    }
}

一些额外注意事项

  • 如果HTML里包含图片,可能需要等图片加载完成后再计算高度,这时候可以在HTML里添加window.onload事件,通过JS通知原生代码重新计算高度。
  • 确保WebView的VerticalOptions设为Fill或者Start,不要固定高度。
  • 若使用Xamarin.Forms 5.0+,Android端推荐切换为WKWebView,渲染器逻辑需要调整为监听NavigationCompleted事件。

内容的提问来源于stack exchange,提问作者Dan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:59:45