使用本地 css Xamarin 表单设置外部网页样式
Styling an external webpage with local css Xamarin forms
我正在从我的后端获取外部页面 HTML 代码作为字符串
并在 Xamarin 表单应用程序的 Webview 中显示它
现在我想设计它的样式
我想知道最有效的方法是什么?
是否可以像使用 XAML 和共享资源设置 Xamarin 页面的样式一样设置它的样式?
到目前为止,我尝试在共享资源中引用一个 CSS 文件,但我发现它不起作用...
htmlData = "<link rel=\"stylesheet\" type=\"text/css\"href=\"Assets\"Styles\"style.css\" />" + htmlData;
htmlSource.Html = htmlData;
myWebView.Source = htmlSource;
更新
我最终为 Webview 使用了自定义渲染器
适用于 Android 但不适用于 IOS
这是我的 IOS 渲染器实现
[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(""));
}
}
}
}
注意:我不知道 IOS 代码在这里发生了什么,因为我从来没有用母语编写代码
我不知道这对你是否可行,但你可以在 HTML 字符串中注入实际的 CSS 然后分配 HtmlSource
var css = ReadStringFromAsset("style.css");
htmlData = InjectCssInHtml(htmlData, css);
htmlSource.Html = htmlData;
myWebView.Source = htmlSource;
根据您对收到的 HTML 的控制程度,您可以选择如何实现 InjectCssInHtml
伪标记评论
如果更改 HTML 可行,您可以添加一个 HTML 注释作为伪标记。这将使代码简单,但每个 HTML 必须相应地编辑
<html>
<head>
<style>
<!-- CSS -->
</style>
...
</html>
你的 InjectCssInHtml
然后变成
string InjectCssInHtml(string html, string css)
{
return html.Replace("<!-- CSS -->", css);
}
不编辑 HTML
如果编辑 HTML 不可行,InjectCssInHtml
会变得有点复杂。以下是初步猜测,但我想你已经明白了
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);
}
当然,这并没有涵盖所有可能的情况,但我想您明白了。 ìf-else` 可以替换为结合策略行为模式的抽象工厂生成模式。
string InjectCssInHtml(string html, string css)
{
ICssInjector injector = injectorFactory.CreateInjector(html);
return injector.InjectCss(html, css);
}
我正在从我的后端获取外部页面 HTML 代码作为字符串
并在 Xamarin 表单应用程序的 Webview 中显示它
现在我想设计它的样式
我想知道最有效的方法是什么?
是否可以像使用 XAML 和共享资源设置 Xamarin 页面的样式一样设置它的样式?
到目前为止,我尝试在共享资源中引用一个 CSS 文件,但我发现它不起作用...
htmlData = "<link rel=\"stylesheet\" type=\"text/css\"href=\"Assets\"Styles\"style.css\" />" + htmlData;
htmlSource.Html = htmlData;
myWebView.Source = htmlSource;
更新
我最终为 Webview 使用了自定义渲染器
适用于 Android 但不适用于 IOS
这是我的 IOS 渲染器实现
[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(""));
}
}
}
}
注意:我不知道 IOS 代码在这里发生了什么,因为我从来没有用母语编写代码
我不知道这对你是否可行,但你可以在 HTML 字符串中注入实际的 CSS 然后分配 HtmlSource
var css = ReadStringFromAsset("style.css");
htmlData = InjectCssInHtml(htmlData, css);
htmlSource.Html = htmlData;
myWebView.Source = htmlSource;
根据您对收到的 HTML 的控制程度,您可以选择如何实现 InjectCssInHtml
伪标记评论
如果更改 HTML 可行,您可以添加一个 HTML 注释作为伪标记。这将使代码简单,但每个 HTML 必须相应地编辑
<html>
<head>
<style>
<!-- CSS -->
</style>
...
</html>
你的 InjectCssInHtml
然后变成
string InjectCssInHtml(string html, string css)
{
return html.Replace("<!-- CSS -->", css);
}
不编辑 HTML
如果编辑 HTML 不可行,InjectCssInHtml
会变得有点复杂。以下是初步猜测,但我想你已经明白了
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);
}
当然,这并没有涵盖所有可能的情况,但我想您明白了。 ìf-else` 可以替换为结合策略行为模式的抽象工厂生成模式。
string InjectCssInHtml(string html, string css)
{
ICssInjector injector = injectorFactory.CreateInjector(html);
return injector.InjectCss(html, css);
}