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

.NET MAUI安卓:ScrollView内自定义WebView内容不可见问题解决

解决.NET MAUI安卓中ScrollView嵌套WebView不显示内容的问题

核心原因

安卓平台上,WebView与ScrollView嵌套时,WebView无法自动计算自身内容高度,导致布局高度被压缩为0,从而无法显示内容。移除ScrollView后,WebView能获取父容器的正确布局约束,因此可以正常显示。

解决方案

方案1:调整XAML布局,为WebView添加高度约束

修改Grid的行定义,将WebView所在行的高度设置为Auto,同时给WebView指定HeightRequest(可先设固定值测试,后续再动态绑定内容高度):

<Frame 
Margin="10,0,10,0"
x:Name="android_uwp_layout"
IsVisible="False"
Padding="5"
CornerRadius="20"
Grid.Row="1">
<ScrollView
    Orientation="Vertical"
    VerticalOptions="FillAndExpand">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" /> <!-- 改为Auto适配WebView内容高度 -->
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <!-- Background Image -->
        <Image Aspect="Fill" HorizontalOptions="FillAndExpand" Grid.Row="0" Source="ic_daily_reading_new_bg_xx.png"/>
        
        <!-- WebView -->
        <local:DailyReadingAndroidWebView  
            x:Name="mywebview"
            Grid.Row="0"
            BackgroundColor="Transparent"
            HorizontalOptions="FillAndExpand"
            VerticalOptions="FillAndExpand"
            HeightRequest="800"/> <!-- 临时固定高度,后续可动态调整 -->

        <!-- Other UI Elements -->
    </Grid>
</ScrollView>

方案2:自定义渲染器中动态计算WebView内容高度

在安卓自定义渲染器中,通过JavaScript获取网页内容高度,再同步给WebView,同时禁用WebView自身滚动避免冲突:

public class DailyReadingAndroidRenderer : WebViewRenderer
{
    public DailyReadingAndroidRenderer(Context context) : base(context)
    {
    }

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

        if (Control != null)
        {
            // 禁用WebView自身滚动,避免与外层ScrollView冲突
            Control.VerticalScrollBarEnabled = false;
            Control.HorizontalScrollBarEnabled = false;

            // 基础WebView配置
            Control.Settings.DefaultFontSize = 25;
            Control.Settings.JavaScriptEnabled = true;
            Control.SetBackgroundColor(Android.Graphics.Color.Transparent);
            Control.SetLayerType(Android.Views.LayerType.Software, null);
            Control.Settings.SetSupportZoom(false);

            // 注入样式+获取内容高度的脚本
            string script = @"
                let style = document.createElement('style');
                style.innerHTML = 
                    @font-face {
                        font-family: 'CustomFont';
                        src: url('file:///android_asset/Poppins-Light.ttf');
                    }
                    body {
                        background-color: transparent !important;
                        color: black !important;
                        font-family: 'CustomFont', sans-serif !important;
                        margin: 0;
                        padding: 0;
                    }
                    h4 {
                        color: #679E18 !important;
                    }
                ;
                document.head.appendChild(style);
                // 将网页高度传递给原生端
                window.android.getDocumentHeight(document.body.scrollHeight);
            ";

            Control.SetWebViewClient(new CustomWebViewClient(script));
            // 添加JS接口接收高度数据
            Control.AddJavascriptInterface(new WebViewJsInterface(Element), "android");
        }
    }

    private class CustomWebViewClient : WebViewClient
    {
        private readonly string _script;

        public CustomWebViewClient(string script) => _script = script;

        public override void OnPageFinished(Android.Webkit.WebView view, string url)
        {
            base.OnPageFinished(view, url);
            view.EvaluateJavascript(_script, null);
        }
    }

    // JS交互类,用于接收网页高度
    private class WebViewJsInterface : Java.Lang.Object
    {
        private readonly Microsoft.Maui.Controls.WebView _webView;

        public WebViewJsInterface(Microsoft.Maui.Controls.WebView webView) => _webView = webView;

        [Android.Webkit.JavascriptInterface]
        public void GetDocumentHeight(int height)
        {
            // 转换安卓px为MAUI dp单位
            float density = Android.App.Application.Context.Resources.DisplayMetrics.Density;
            int dpHeight = (int)(height / density);
            // 在UI线程更新WebView高度
            Microsoft.Maui.Controls.Device.BeginInvokeOnMainThread(() =>
            {
                _webView.HeightRequest = dpHeight;
            });
        }
    }
}

方案3:拆分布局避免嵌套(变通方案)

如果布局允许,将WebView与ScrollView拆分到不同的Grid行,只让需要滚动的元素放在ScrollView中:

<Frame 
Margin="10,0,10,0"
x:Name="android_uwp_layout"
IsVisible="False"
Padding="5"
CornerRadius="20"
Grid.Row="1">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <!-- WebView和背景图单独占一行,不嵌套ScrollView -->
        <Grid Grid.Row="0">
            <Image Aspect="Fill" HorizontalOptions="FillAndExpand" Source="ic_daily_reading_new_bg_xx.png"/>
            <local:DailyReadingAndroidWebView  
                x:Name="mywebview"
                BackgroundColor="Transparent"
                HorizontalOptions="FillAndExpand"
                VerticalOptions="FillAndExpand"/>
        </Grid>

        <!-- 其他需要滚动的元素放在ScrollView中 -->
        <ScrollView Grid.Row="1" Orientation="Vertical" VerticalOptions="FillAndExpand">
            <!-- 其他UI元素 -->
        </ScrollView>
    </Grid>
</Frame>

注意事项

  • 必须禁用WebView自身滚动条,避免与外层ScrollView的滚动逻辑冲突。
  • 动态计算高度时要做好单位转换,防止高度显示异常。
  • 若WebView内容动态更新,需重新执行高度计算脚本。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 10:34:52