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

如何适配ListView中WebView高度:含图自适应/无图固定60?

解决ListView中WebView高度动态适配问题

核心思路

WebView加载完成后通过JS注入获取页面实际高度,传递回C#端动态设置HeightRequest;同时在解析内容时判断是否包含图片,无图时强制固定高度为60。

具体实现步骤

1. 调整XAML绑定逻辑

给ListView的WebView新增HeightRequest绑定,保留NavigationCompleted事件用于加载完成后的高度计算:

<ListView ItemsSource="{Binding Items}" x:Name="MyListView">
    <ListView.ItemTemplate>
        <DataTemplate>
            <WebView 
                Source="{Binding HtmlContent}" 
                NavigationCompleted="WebView_NavigationCompleted"
                HeightRequest="{Binding WebViewHeight}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

这里WebViewHeight是列表项ViewModel中的属性,用于动态控制高度。

2. 完善列表项ViewModel

确保每个列表项的ViewModel包含以下属性(需实现INotifyPropertyChanged接口):

public class ItemViewModel : INotifyPropertyChanged
{
    public HtmlWebViewSource HtmlContent { get; set; }
    public bool HasImage { get; set; }

    private double _webViewHeight = 60; // 默认无图高度
    public double WebViewHeight
    {
        get => _webViewHeight;
        set
        {
            _webViewHeight = value;
            OnPropertyChanged(nameof(WebViewHeight));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

解析JSON时,直接判断HTML内容是否包含<img>标签,标记HasImage:

// 解析JSON示例
foreach (var jsonItem in jsonData)
{
    var rawHtml = jsonItem.Content;
    var processedHtml = $@"
        <html>
        <head>
            <style>img {{ max-width: 100%; height: auto; }} body {{ margin:0; padding:8px; }}</style>
        </head>
        <body>{rawHtml}</body>
        </html>";

    items.Add(new ItemViewModel
    {
        HtmlContent = new HtmlWebViewSource { Html = processedHtml },
        HasImage = rawHtml.Contains("<img")
    });
}

预处理HTML时给图片添加自适应样式,避免图片超出WebView宽度导致高度计算偏差。

3. 修复NavigationCompleted事件逻辑

仅当内容包含图片时,注入JS获取页面实际高度并更新:

private async void WebView_NavigationCompleted(object sender, WebViewNavigationCompletedEventArgs e)
{
    var webView = sender as WebView;
    var itemVm = webView.BindingContext as ItemViewModel;

    if (itemVm == null || !itemVm.HasImage) return;

    // 注入JS获取页面滚动高度
    var heightScript = "document.body.scrollHeight.toString()";
    var heightResult = await webView.EvaluateJavaScriptAsync(heightScript);

    if (double.TryParse(heightResult, out double actualHeight))
    {
        // 增加20px冗余高度避免内容被截断
        itemVm.WebViewHeight = actualHeight + 20;
        // 强制刷新ListView布局
        MyListView.ForceLayout();
    }
}

4. 解决布局不刷新问题

如果设置高度后ListView未及时更新,可在WebViewHeight属性变更时触发布局刷新,上面代码中已经通过MyListView.ForceLayout()实现,确保高度变化后UI能同步更新。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 20:40:56