Search code examples
c#iosmauiwkwebviewmaui-ios

MAUI Webview won't open local page on IOS


I am trying to make my app available on IOS as well but I seem to encounter a problem with the webView implementation. I have the following page:

NewsArticle.xaml

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:testApp="clr-namespace:TestApp"
             Loaded="PageLoaded"
             x:DataType="testApp:NewsArticleViewModel"
             x:Class="TestApp.NewsArticle">
    <Grid
            x:Name="NewsScrollView">
        <WebView
                IsVisible="true"
                Navigating="WebView_Navigating">
            <WebView.Source>
                <HtmlWebViewSource Html="{Binding ArticleContent}"/>
            </WebView.Source>
        </WebView>
    </Grid>
</ContentPage>

with the following code behind:

public partial class NewsArticle : ContentPage
{
    public readonly NewsArticleViewModel ViewModel;
    public NewsArticle(NewsArticleViewModel viewModel)
    {
        ViewModel = viewModel;
        BindingContext = viewModel;
        InitializeComponent();
        if (DeviceInfo.Platform == DevicePlatform.WinUI)
        {
            NewsScrollView.MaximumHeightRequest = 750;
        }
        else
        {
            NewsScrollView.MaximumHeightRequest = DeviceDisplay.MainDisplayInfo.Height / DeviceDisplay.MainDisplayInfo.Density * 0.6;
        }
    }
    protected void PageLoaded(object sender, EventArgs e)
    {
        ((NewsArticleViewModel)ViewModel).GetSpecificNews();
    }

    private void WebView_Navigating(object sender, WebNavigatingEventArgs e)
    {
        e.Cancel = true;
        ((NewsArticleViewModel)ViewModel).NavigateUsingDeviceBrowser(e.Url);
    }
}

and its viewmodel:


using CommunityToolkit.Mvvm.ComponentModel;
using System.Text.RegularExpressions;


namespace TestApp
{
    public partial class NewsArticleViewModel : ObservableObject
    {

        [ObservableProperty] private string _articleContent;

        [ObservableProperty] private string _article;

        public NewsArticleViewModel()
        {
        }


        public void GetSpecificNews()
        {

            Article = "<p></p><p>What is Lorem Ipsum?<span></span></p><p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>";

            if (DeviceInfo.Current.Platform == DevicePlatform.WinUI)
                ArticleContent = "Not Available on windows";
            else
            {
                var appTheme = Application.Current.RequestedTheme;
                var textColor = appTheme == AppTheme.Light ? "#000000" : "#FBF9F9";

                ArticleContent = $@"<HTML><head><meta name='viewport' content='width=device-width,initial-scale=1,maximum-scale=1' /><style>p{{color:{textColor}}} a{{color:#408F70}} ul li span{{color:{textColor} !important}} ul li a{{color:#408F70 !important}} img{{display: inline;height: auto;max-width: 100%;}} video{{display: inline;height: auto;max-width: 100%; allowfullscreen: true;}}</style></head><BODY>{ToBasicHtml(Article)}</BODY></HTML>";
            }

        }

        public string ToBasicHtml(string url)
        {
            if (string.IsNullOrEmpty(url))
                return "";
            return Regex.Replace(url, "<img(.*?)>", "<img $1 />");
        }


        public async void NavigateUsingDeviceBrowser(string url)
        {
            try
            {
                var uri = new Uri(url);
                await Browser.Default.OpenAsync(uri, BrowserLaunchMode.External);
            }
            catch (Exception ex)
            {
                return;
            }
        }
    }
}

On android the content is loading properly and the page is being displayed according to the local HTML, but on IOS the only thing I get shown on screen is a blank page. I tried implementing a custom IOS handler, but it didn't work for me. How can I fix this and get the page displayed ?


Solution

  • I can reproduce your issue on iOS. The issue is only existing on iOS when calling Navigating="WebView_Navigating". Since you are only loading local html page, to fix it you may remove it from your project like below:

    <Grid
                x:Name="NewsScrollView">
            <WebView
                    IsVisible="true"
                   >
                <WebView.Source>
                    <HtmlWebViewSource Html="{Binding ArticleContent}"/>
                </WebView.Source>
            </WebView>
    </Grid>
    

    Output:

    enter image description here

    Reference link:

    https://learn.microsoft.com/en-us/dotnet/maui/user-interface/controls/webview?pivots=devices-ios#Display%20local%20HTML