0

I'm getting an external page HTML code from my Backend as a string

and displaying it in a Webview in a Xamarin forms app

Now I would like to style it

I was wondering what is the most efficient way to do that?

and is it possible to style it in the same way a Xamarin Page would get styled with XAML and shared resources?

so far I tried referencing a CSS file in the shared resources, which I found out doesn't work...

htmlData = "<link rel=\"stylesheet\" type=\"text/css\"href=\"Assets\"Styles\"style.css\" />" + htmlData; 
htmlSource.Html = htmlData;
myWebView.Source = htmlSource;

Update

I ended up using a custom renderer for the Webview

which worked for Android but not for IOS

here is my IOS implementation of the renderer

    [assembly: ExportRenderer(typeof(CustomWebView), typeof(CustomWebViewRenderer))]
namespace XXX.iOS.Renderers
{
    public class CustomWebViewRenderer : WkWebViewRenderer
    {
        WKUserContentController userController;

        public CustomWebViewRenderer() : this(new WKWebViewConfiguration())
        {
        }
        public CustomWebViewRenderer(WKWebViewConfiguration config) : base(config)
        {
            userController = config.UserContentController;
        }

        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            var customWebView = e.NewElement as CustomWebView;

            if (e.NewElement != null)
            {
                string htmldata = customWebView.HTMLData;

                htmldata = "<link rel=\"stylesheet\" type=\"text/css\" href=\"StyleSheet.css\" />" + htmldata;

                WkWebViewRenderer wkWebViewRenderer = new WkWebViewRenderer();

                NSData data = NSData.FromString(htmldata);

                wkWebViewRenderer.LoadData(data,"text/html", "UTF-8",new NSUrl(""));
            }
        }
    }
}

Note: I don't have any idea what is happening here with the IOS code, cause I have never coded in the native language

1 Answer 1

1

I don't know whether this is feasible for you, but you could inject the actual CSS in the HTML string and then assign the HtmlSource

var css = ReadStringFromAsset("style.css");
htmlData = InjectCssInHtml(htmlData, css);
htmlSource.Html = htmlData;
myWebView.Source = htmlSource;

Depending on how much control you have over the HTML you receive, you have several option on how to realize InjectCssInHtml

Pseudo-Markup comment

If changing the HTML is feasible, you could add an HTML comment as a pdeudo markup. This will make the code simple, but each HTML must be edited accordingly

<html>
<head>
<style>
<!-- CSS -->
</style>
...
</html>

your InjectCssInHtml then becomes

string InjectCssInHtml(string html, string css)
{
    return html.Replace("<!-- CSS -->", css);
}

Without editing the HTML

If editing the HTML is not feasible, the InjectCssInHtml becomes a tad more complicated. The following is a first guess, but I think you get the idea

string InjectCssInHtml(string html, string css)
{
    string codeToInject;
    int indexToInject = 0;

    if(ContainsStyleTag(html))
    {
        indexToInject = IndexOfStyleTagContent(html);
        codeToInject = css;
    }
    else if(ContainsHeadTag(html))
    {
        indexToInject = IndexOfHeadTagContents(html);
        codeToInject = $"<style>{css}</style>";
    }
    else
    {
        indexToInject = IndexOfHtmlTagContents(html);
        codeToInject = $"<head><style>{css}</style></head>";
    }

    return html.Insert(indexToInject, codeToInject);
}

Surely this does not cover each possible case, but I think you get the idea. The ìf-else` could be replaced by an abstract factory generational pattern combined with the strategy behavioral pattern.

string InjectCssInHtml(string html, string css)
{
    ICssInjector injector = injectorFactory.CreateInjector(html);
    return injector.InjectCss(html, css);

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.