最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

MAUI: How to update the webview height after loading new content - Stack Overflow

programmeradmin1浏览0评论

I want to implement the below UI in my MAUI application (header and footer sections are not added):

Below is my code (header and footer sections are not added): Webview to show HTML content(with a background image), Audio frame with previous, play and next options and finally a footer image.

<Frame 
    Margin="10,0,10,0"
    x:Name="android_uwp_layout"
    IsVisible="False"
    Padding="0"
    CornerRadius="20"
    Grid.Row="1">

    <ScrollView 
        x:Name="android_scroll_view"
        Orientation="Vertical" 
        VerticalOptions="FillAndExpand">
        <VerticalStackLayout Spacing="10">

            <!-- Background image with WebView -->
            <Grid>
                <Image Aspect="Fill" HorizontalOptions="FillAndExpand" Source="ic_daily_reading_new_bg_xx.png"/>

                <WebView  
                    x:Name="mywebview"
                    BackgroundColor="Transparent"
                    HorizontalOptions="FillAndExpand"
                    VerticalOptions="FillAndExpand"
                    Navigated="OnWebViewNavigated"/>
            </Grid>

            <!-- Audio frame (Appears after WebView content) -->
            <Frame
                x:Name="android_audio_frame"
                BackgroundColor="#666664"
                Padding="0"
                CornerRadius="{OnIdiom Phone=30, Tablet=45, Desktop=30}"
                Margin="0,10,0,15"
                HorizontalOptions="CenterAndExpand"
                VerticalOptions="EndAndExpand">

                //Audio frame UI with previous, play and next options
            </Frame>

            <!-- Footer image (Appears at the bottom) -->
            <ffimageloading:CachedImage 
                Aspect="AspectFit"
                HorizontalOptions="Fill"
                VerticalOptions="End"
                Source="ic_jesus_xx.png"/>
        </VerticalStackLayout>
    </ScrollView>
</Frame>

I integrated the HTML content to webview like below: (Added custom font and added a different color for header contents)

string description = Details.description;
string htmlContent = $@"
        <html>
        <head>
            <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'/>
            <style>
                @font-face {{
                    font-family: 'PoppinsLight';
                    src: url('file:///android_asset/fonts/Poppins-Light.ttf');
                }}
                html, body {{
                    font-family: 'PoppinsLight', Arial, sans-serif;
                    margin: 0;
                    padding: 5;
                    line-height: 1.6;
                    overflow-x: hidden;
                    height: 100%;
                }}
                h4 {{
                    color: #679E18;
                }}
            </style>
        </head>
        <body>
            {description}
        </body>
        </html>";
var htmlSource = new HtmlWebViewSource
{
    Html = htmlContent
};
mywebview.Source = htmlSource;

Everything is working fine when load data initially. My Problem is when refreshing the content via API either blank space is showing in webview bottom or the entire webview content is not showing on the UI. The initially loaded height is not changing when loading the new content.

I have added Navigated event for webview, but it only fires when loading the data on initial time.

private async void OnWebViewNavigated(object sender, WebNavigatedEventArgs e)
{
    await Task.Delay(500); // Allow time for content to load

    string js = "document.body.scrollHeight";
    var height = await mywebview.EvaluateJavaScriptAsync(js);

    if (double.TryParse(height, out double newHeight) && newHeight > 0)
    {
        mywebview.HeightRequest = newHeight;  // Set WebView height dynamically
    }
}

Please check this video for a clear understanding.

I tried creating a new function with the OnWebViewNavigated logic like below:

//setting html data to webview
mywebview.Source = htmlSource;
await Task.Delay(500);
await AdjustWebViewHeight();
                                    
private async Task AdjustWebViewHeight()
{
    string js = "document.body.scrollHeight";
    var height = await mywebview.EvaluateJavaScriptAsync(js);

    if (double.TryParse(height, out double newHeight) && newHeight > 0)
   {
        mywebview.HeightRequest = newHeight;
   }
}

But at that time the UI completely breaks. Showing blank space on top and font styles are changing with that approach. In this video I have added what kind of issues with the new logic I tried.

Please suggest a solution to update the webview height based on the content without affecting the font family and blank spaces.

I want to implement the below UI in my MAUI application (header and footer sections are not added):

Below is my code (header and footer sections are not added): Webview to show HTML content(with a background image), Audio frame with previous, play and next options and finally a footer image.

<Frame 
    Margin="10,0,10,0"
    x:Name="android_uwp_layout"
    IsVisible="False"
    Padding="0"
    CornerRadius="20"
    Grid.Row="1">

    <ScrollView 
        x:Name="android_scroll_view"
        Orientation="Vertical" 
        VerticalOptions="FillAndExpand">
        <VerticalStackLayout Spacing="10">

            <!-- Background image with WebView -->
            <Grid>
                <Image Aspect="Fill" HorizontalOptions="FillAndExpand" Source="ic_daily_reading_new_bg_xx.png"/>

                <WebView  
                    x:Name="mywebview"
                    BackgroundColor="Transparent"
                    HorizontalOptions="FillAndExpand"
                    VerticalOptions="FillAndExpand"
                    Navigated="OnWebViewNavigated"/>
            </Grid>

            <!-- Audio frame (Appears after WebView content) -->
            <Frame
                x:Name="android_audio_frame"
                BackgroundColor="#666664"
                Padding="0"
                CornerRadius="{OnIdiom Phone=30, Tablet=45, Desktop=30}"
                Margin="0,10,0,15"
                HorizontalOptions="CenterAndExpand"
                VerticalOptions="EndAndExpand">

                //Audio frame UI with previous, play and next options
            </Frame>

            <!-- Footer image (Appears at the bottom) -->
            <ffimageloading:CachedImage 
                Aspect="AspectFit"
                HorizontalOptions="Fill"
                VerticalOptions="End"
                Source="ic_jesus_xx.png"/>
        </VerticalStackLayout>
    </ScrollView>
</Frame>

I integrated the HTML content to webview like below: (Added custom font and added a different color for header contents)

string description = Details.description;
string htmlContent = $@"
        <html>
        <head>
            <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'/>
            <style>
                @font-face {{
                    font-family: 'PoppinsLight';
                    src: url('file:///android_asset/fonts/Poppins-Light.ttf');
                }}
                html, body {{
                    font-family: 'PoppinsLight', Arial, sans-serif;
                    margin: 0;
                    padding: 5;
                    line-height: 1.6;
                    overflow-x: hidden;
                    height: 100%;
                }}
                h4 {{
                    color: #679E18;
                }}
            </style>
        </head>
        <body>
            {description}
        </body>
        </html>";
var htmlSource = new HtmlWebViewSource
{
    Html = htmlContent
};
mywebview.Source = htmlSource;

Everything is working fine when load data initially. My Problem is when refreshing the content via API either blank space is showing in webview bottom or the entire webview content is not showing on the UI. The initially loaded height is not changing when loading the new content.

I have added Navigated event for webview, but it only fires when loading the data on initial time.

private async void OnWebViewNavigated(object sender, WebNavigatedEventArgs e)
{
    await Task.Delay(500); // Allow time for content to load

    string js = "document.body.scrollHeight";
    var height = await mywebview.EvaluateJavaScriptAsync(js);

    if (double.TryParse(height, out double newHeight) && newHeight > 0)
    {
        mywebview.HeightRequest = newHeight;  // Set WebView height dynamically
    }
}

Please check this video for a clear understanding.

I tried creating a new function with the OnWebViewNavigated logic like below:

//setting html data to webview
mywebview.Source = htmlSource;
await Task.Delay(500);
await AdjustWebViewHeight();
                                    
private async Task AdjustWebViewHeight()
{
    string js = "document.body.scrollHeight";
    var height = await mywebview.EvaluateJavaScriptAsync(js);

    if (double.TryParse(height, out double newHeight) && newHeight > 0)
   {
        mywebview.HeightRequest = newHeight;
   }
}

But at that time the UI completely breaks. Showing blank space on top and font styles are changing with that approach. In this video I have added what kind of issues with the new logic I tried.

Please suggest a solution to update the webview height based on the content without affecting the font family and blank spaces.

Share Improve this question asked Mar 15 at 10:53 Matthew PansMatthew Pans 8751 gold badge11 silver badges29 bronze badges 8
  • Is it just an Android issue and do you use any webViewRenderer? Could you please share a Minimal, Reproducible Example with all private data removed? – Felix Shen Commented Mar 17 at 2:52
  • @LiqunShen-MSFT It is just an issue on the Android platform, no webViewRenderer I am using. I will create a demo and share here ASAP. – Matthew Pans Commented Mar 17 at 4:37
  • @LiqunShen-MSFT I have created a demo, could you please check with that? drive.google/file/d/1yvjKJuIL6b-gIsdUcm7Xhl_cthFCak5-/… – Matthew Pans Commented Mar 17 at 5:19
  • @LiqunShen-MSFT I have used the same codes in this demo, but when loading data initially also the height is not correct, height is increasing gradually without stopping. To refresh data choose calendar option and choose any data. Could you please help me to resolve it today itself, since today is the last date of the deadline of this project. – Matthew Pans Commented Mar 17 at 5:21
  • height is increasing gradually without stopping. Is it only happening in this demo? – Felix Shen Commented Mar 17 at 7:41
 |  Show 3 more comments

1 Answer 1

Reset to default 1
  • Update

I share a workaround to adjust height when changing the WebView Source using Maui Handler.

In code behind, first we customize a ModifyWebView Handler in constructor.

We create a CustomWebViewClient class and set it to platformWebView.

    public DailyReadingPage()
    {
        InitializeComponent();

        ModifyWebView();
        ...
        CallDailyReading(htmldata);
    }

    void ModifyWebView()
    {
            Microsoft.Maui.Handlers.WebViewHandler.Mapper.AppendToMapping("MyCustomization", (handler, view) =>
        {
#if ANDROID
            if (handler.PlatformView is global::Android.Webkit.WebView platformWebView)
            {
                 platformWebView.SetWebViewClient(new CustomWebViewClient(this.mywebview));
            }
#endif
        });
    }

Here is the code for CustomWebViewClient class, you can place it just in code behind,

#if ANDROID
    public class CustomWebViewClient : WebViewClient
    {

        Microsoft.Maui.Controls.WebView mywebview;
        public CustomWebViewClient(Microsoft.Maui.Controls.WebView webView)
        {
            
            mywebview = webView;
            //mywebview.HeightRequest = 0;
        }

        public async override void OnPageFinished(Android.Webkit.WebView view, string url)
        {
            mywebview.HeightRequest = 0;
            await Task.Delay(500); // Allow time for content to load

            string js = "document.body.scrollHeight";
            var height = await mywebview.EvaluateJavaScriptAsync(js);

            if (double.TryParse(height, out double newHeight) && newHeight > 0)
            {
                mywebview.HeightRequest = newHeight;  // Set WebView height dynamically
            }

            base.OnPageFinished(view, url);


        }

    }
#endif

Just set the height: 100% is okay.

It will adjust the size then.


By the way, though it seems not necessary, you could also try adding the PropertyChanged event for the WebView and implement it. The code is shown below for your reference, hope it helps!

 <WebView  PropertyChanged="mywebview_PropertyChanged"
     x:Name="mywebview"

and implement it in code behind,

    private void mywebview_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
#if ANDROID
        if (e.PropertyName == "Source")
        {
            if (this.mywebview.Handler != null)
                (this.mywebview.Handler.PlatformView as Android.Webkit.WebView).SetWebViewClient(new CustomWebViewClient(this.mywebview));
        }
#endif
    }
发布评论

评论列表(0)

  1. 暂无评论