MAUI: Full content is not showing on the UI with Webview

Sreejith Sreenivasan 961 Reputation points
2025-03-08T11:25:34.6733333+00:00

I am using WebView to show Html content on the UI. I want few customizations in the content like different color for headings and custom font for the entire data. So I used a custom webview like below:

DailyReadingAndroidWebView

public class DailyReadingAndroidWebView : WebView
{
    public static readonly BindableProperty UrlProperty = BindableProperty.Create(
     propertyName: "Url",
     returnType: typeof(string),
     declaringType: typeof(DailyReadingAndroidWebView),
     defaultValue: default(string));

    public string Url
    {
        get { return (string)GetValue(UrlProperty); }
        set { SetValue(UrlProperty, value); }
    }
}

DailyReadingAndroidRenderer

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)
        {
            // Set default font size
            Control.Settings.DefaultFontSize = 25;
            Control.Settings.JavaScriptEnabled = true;

            // Make WebView background transparent via CSS; no need to force software layer
            Control.SetBackgroundColor(Android.Graphics.Color.Transparent);
            // Removed: Control.SetLayerType(Android.Views.LayerType.Software, null);
            Control.Settings.SetSupportZoom(false);

            string makeTransparentScript = @"
            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;
                }
                h4 {
                    color: #679E18 !important;
                }
            `;
            document.head.appendChild(style);
        ";

            Control.SetWebViewClient(new CustomWebViewClient(makeTransparentScript));
        }
    }

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

XAML

<local:DailyReadingAndroidWebView  
    x:Name="mywebview"
    Grid.Row="0"
    BackgroundColor="Transparent"
    HorizontalOptions="FillAndExpand"
    VerticalOptions="FillAndExpand"/>

XAML.CS

string htmldata = "<h4>First Reading - Adapted from Sir. 35:1-12</h4>The person who keeps the law offers much to God; he who keeps the commandments makes a peace offering.  The one who returns a kindness offers fine flour; the person who gives to the poor makes an offering of thanks.  To keep away from wickedness is pleasing to the Lord, and to avoid injustice atones for sin.  Do not appear before the Lord empty-handed, for these things are to be done because of the commandment.<br><br>The offerings of a just man enrich the altar, and its pleasing odor rises before the Most High.  The sacrifice of a good man is acceptable, and it will not be forgotten.  Generously glorify the Lord, and do not hold back your gifts.  Give your gifts with gladness and a cheerful face.  Give to the Most High as he has given, as generously as you have received.  For the Lord is the one who repays, and he will repay you seven times more than you give.<br><br>Do not offer the Lord a bribe, for he will not accept it; and do not trust an unrighteous offering.  For the Lord is the judge, and he does not show favoritism.<br><br><h4 open=\"\" sans\",=\"\" \"helvetica=\"\" neue\",=\"\" helvetica,=\"\" arial,=\"\" sans-serif;\"=\"\" style=\"font-family: \">Psalm 50:5-8, 14, 23</h4>\"Gather to me my faithful ones,<br>who made a covenant with me by sacrifice!\"<br>The heavens declare his righteousness,<br>for God himself is judge!<br>\"Hear, O my people, and I will speak,<br>O Israel, I will testify against you.<br>I am God, your God.<br>I do not reprove you for your sacrifices;<br>your burnt offerings are continually before me.<br>Offer to God a sacrifice of thanksgiving,<br>and pay your vows to the Most High;<br>He who brings thanksgiving as his sacrifice honors me;<br>to him who orders his way aright<br>I will show the salvation of God!\"<br><br><h4 open=\"\" sans\",=\"\" \"helvetica=\"\" neue\",=\"\" helvetica,=\"\" arial,=\"\" sans-serif;\"=\"\" style=\"font-family: \">Gospel - Adapted from Mark 10:28-31</h4>Peter began to say to Jesus, \"We gave up everything and followed you.\" Jesus said, \"Truly, everyone who has given up a home, or brothers, or sisters, or mother, father, or children, or lands for my sake will receive a hundred times more in this world: houses and brothers and sisters and mothers and children and lands, along with sufferings; and they will receive everlasting life in the world to come.  But many people that are first will be last, and the last will be first.\"<br>";
string description = htmldata.Replace("&#39;", "'").Replace("src=\"//player.vimeo.com/video", "src=\"https://player.vimeo.com/video");
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = description.Replace("width=\"640\" height=\"360\"", "width=\"350\" height=\"350\"");
mywebview.Source = htmlSource;

I am using WebView to show Html content on the UI. I want few customizations in the content like different color for headings and custom font for the entire data. So I used a custom webview like below:

DailyReadingAndroidWebView

public class DailyReadingAndroidWebView : WebView
{
    public static readonly BindableProperty UrlProperty = BindableProperty.Create(
     propertyName: "Url",
     returnType: typeof(string),
     declaringType: typeof(DailyReadingAndroidWebView),
     defaultValue: default(string));

    public string Url
    {
        get { return (string)GetValue(UrlProperty); }
        set { SetValue(UrlProperty, value); }
    }
}

DailyReadingAndroidRenderer

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)
        {
            // Set default font size
            Control.Settings.DefaultFontSize = 25;
            Control.Settings.JavaScriptEnabled = true;

            // Make WebView background transparent via CSS; no need to force software layer
            Control.SetBackgroundColor(Android.Graphics.Color.Transparent);
            // Removed: Control.SetLayerType(Android.Views.LayerType.Software, null);
            Control.Settings.SetSupportZoom(false);

            string makeTransparentScript = @"
            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;
                }
                h4 {
                    color: #679E18 !important;
                }
            `;
            document.head.appendChild(style);
        ";

            Control.SetWebViewClient(new CustomWebViewClient(makeTransparentScript));
        }
    }

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

XAML

<local:DailyReadingAndroidWebView  
    x:Name="mywebview"
    Grid.Row="0"
    BackgroundColor="Transparent"
    HorizontalOptions="FillAndExpand"
    VerticalOptions="FillAndExpand"/>

XAML.CS

string htmldata = "<h4>First Reading - Adapted from Sir. 35:1-12</h4>The person who keeps the law offers much to God; he who keeps the commandments makes a peace offering.  The one who returns a kindness offers fine flour; the person who gives to the poor makes an offering of thanks.  To keep away from wickedness is pleasing to the Lord, and to avoid injustice atones for sin.  Do not appear before the Lord empty-handed, for these things are to be done because of the commandment.<br><br>The offerings of a just man enrich the altar, and its pleasing odor rises before the Most High.  The sacrifice of a good man is acceptable, and it will not be forgotten.  Generously glorify the Lord, and do not hold back your gifts.  Give your gifts with gladness and a cheerful face.  Give to the Most High as he has given, as generously as you have received.  For the Lord is the one who repays, and he will repay you seven times more than you give.<br><br>Do not offer the Lord a bribe, for he will not accept it; and do not trust an unrighteous offering.  For the Lord is the judge, and he does not show favoritism.<br><br><h4 open=\"\" sans\",=\"\" \"helvetica=\"\" neue\",=\"\" helvetica,=\"\" arial,=\"\" sans-serif;\"=\"\" style=\"font-family: \">Psalm 50:5-8, 14, 23</h4>\"Gather to me my faithful ones,<br>who made a covenant with me by sacrifice!\"<br>The heavens declare his righteousness,<br>for God himself is judge!<br>\"Hear, O my people, and I will speak,<br>O Israel, I will testify against you.<br>I am God, your God.<br>I do not reprove you for your sacrifices;<br>your burnt offerings are continually before me.<br>Offer to God a sacrifice of thanksgiving,<br>and pay your vows to the Most High;<br>He who brings thanksgiving as his sacrifice honors me;<br>to him who orders his way aright<br>I will show the salvation of God!\"<br><br><h4 open=\"\" sans\",=\"\" \"helvetica=\"\" neue\",=\"\" helvetica,=\"\" arial,=\"\" sans-serif;\"=\"\" style=\"font-family: \">Gospel - Adapted from Mark 10:28-31</h4>Peter began to say to Jesus, \"We gave up everything and followed you.\" Jesus said, \"Truly, everyone who has given up a home, or brothers, or sisters, or mother, father, or children, or lands for my sake will receive a hundred times more in this world: houses and brothers and sisters and mothers and children and lands, along with sufferings; and they will receive everlasting life in the world to come.  But many people that are first will be last, and the last will be first.\"<br>";
string description = htmldata.Replace("&#39;", "'").Replace("src=\"//player.vimeo.com/video", "src=\"https://player.vimeo.com/video");
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = description.Replace("width=\"640\" height=\"360\"", "width=\"350\" height=\"350\"");
mywebview.Source = htmlSource;

My problem is html content is not full showing on the UI.

More Details about the other controls in the UI:

I have a audio section and a footer image on bottom of the webview. Also I need to show the webview contents with a background image. Below is the complete UI.

<Frame 
    Margin="10,0,10,0"
    x:Name="android_uwp_layout"
    Padding="0"
    CornerRadius="20"
    Grid.Row="1">
    <ScrollView
        Orientation="Vertical"
        VerticalOptions="FillAndExpand">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <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"/>

            <!-- Main content -->
            <local:DailyReadingAndroidWebView  
                x:Name="mywebview"
                Grid.Row="0"
                BackgroundColor="Transparent"
                HorizontalOptions="FillAndExpand"
                VerticalOptions="FillAndExpand"/>

            <!-- Audio frame -->
            <Frame
                x:Name="android_audio_frame"
                Grid.Row="1"
                BackgroundColor="#666664"
                Padding="0"
                CornerRadius="{OnIdiom Phone=30, Tablet=45, Desktop=30}"
                Margin="0,10,0,15"
                HorizontalOptions="CenterAndExpand"
                VerticalOptions="EndAndExpand">

                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="25*" />
                        <ColumnDefinition Width="50*" />
                        <ColumnDefinition Width="25*" />
                    </Grid.ColumnDefinitions>

                    <Image
                        Grid.Column="0"
                        HorizontalOptions="StartAndExpand"
                        VerticalOptions="CenterAndExpand"
                        Margin="15,0,0,0"
                        Source="ic_audio_previous_play_icon_xx.png">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer
                                Tapped="PlayPreviousAudio"
                                NumberOfTapsRequired="1">
                            </TapGestureRecognizer>
                        </Image.GestureRecognizers>
                    </Image>

                    <Image
                        Grid.Column="1"
                        Margin="0,2,0,2"
                        HorizontalOptions="CenterAndExpand"
                        VerticalOptions="CenterAndExpand"
                        Source="ic_daily_reading_audio_play_icon_xx.png">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer
                                Tapped="PlayAudio"
                                NumberOfTapsRequired="1">
                            </TapGestureRecognizer>
                        </Image.GestureRecognizers>
                    </Image>

                    <Image
                        Grid.Column="2"
                        HorizontalOptions="EndAndExpand"
                        VerticalOptions="CenterAndExpand"
                        Margin="0,0,15,0"
                        Source="ic_audio_next_play_icon_xx.png">
                        <Image.GestureRecognizers>
                            <TapGestureRecognizer
                                Tapped="PlayNextAudio"
                                NumberOfTapsRequired="1">
                            </TapGestureRecognizer>
                        </Image.GestureRecognizers>
                    </Image>
                </Grid>

                <Frame.WidthRequest>
                    <OnIdiom x:TypeArguments="x:Double">
                        <OnIdiom.Phone>340</OnIdiom.Phone>
                        <OnIdiom.Tablet>510</OnIdiom.Tablet>
                        <OnIdiom.Desktop>340</OnIdiom.Desktop>
                    </OnIdiom>
                </Frame.WidthRequest>
                <Frame.HeightRequest>
                    <OnIdiom x:TypeArguments="x:Double">
                        <OnIdiom.Phone>64</OnIdiom.Phone>
                        <OnIdiom.Tablet>96</OnIdiom.Tablet>
                        <OnIdiom.Desktop>64</OnIdiom.Desktop>
                    </OnIdiom>
                </Frame.HeightRequest>
            </Frame>

            <!-- Footer image -->
            <ffimageloading:CachedImage 
                Grid.Row="2"
                Aspect="AspectFit"
                HorizontalOptions="Fill"
                VerticalOptions="End"
                Source="ic_jesus_xx.png">
                <!-- <ffimageloading:CachedImage.HeightRequest>
                    <OnIdiom x:TypeArguments="x:Double">
                        <OnIdiom.Phone>200</OnIdiom.Phone>
                        <OnIdiom.Tablet>300</OnIdiom.Tablet>
                        <OnIdiom.Desktop>200</OnIdiom.Desktop>
                    </OnIdiom>
                </ffimageloading:CachedImage.HeightRequest> -->
            </ffimageloading:CachedImage>
        </Grid>
    </ScrollView>
</Frame>

Screenshot

as

As you can see in the screenshot, the last sentence is Give to the Most High as he has given, as generously as you have received. After that also there is a lot of contents.

I have created a demo project to replicate this issue. The demo has only dummy data and it is uploaded here.

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
3,982 questions
0 comments No comments
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.