[英]Xamarin.Forms UWP - Display HTML in a Label
在Xamarin.Forms中,如何在标签中显示HTML? 换句话说,如果我有new Label { Text = "some text and <b>some bold text</b>" }
,我希望它显示为“一些文本和一些粗体文本 ”。
我知道我需要使用自定义渲染器,并且已经在iOS中实现。 我只是不知道如何在UWP中实现它。
根据您的需求,您可以通过自定义LabelRenderer
实现此功能,并且在本机项目中,可以将HtmlTextBehavior
用作TextBlock
。 以下是Behavior
处理逻辑。
public class HtmlTextBehavior : Behavior<TextBlock>
{
private const string ElementA = "A";
private const string ElementB = "B";
private const string ElementBr = "BR";
private const string ElementEm = "EM";
private const string ElementI = "I";
private const string ElementP = "P";
private const string ElementStrong = "STRONG";
private const string ElementU = "U";
private const string ElementUl = "UL";
private const string ElementLi = "LI";
private const string ElementDiv = "DIV";
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += OnAssociatedObjectLoaded;
AssociatedObject.LayoutUpdated += OnAssociatedObjectLayoutUpdated;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= OnAssociatedObjectLoaded;
AssociatedObject.LayoutUpdated -= OnAssociatedObjectLayoutUpdated;
}
private void OnAssociatedObjectLayoutUpdated(object sender, object o)
{
UpdateText();
}
private void OnAssociatedObjectLoaded(object sender, RoutedEventArgs routedEventArgs)
{
UpdateText();
AssociatedObject.Loaded -= OnAssociatedObjectLoaded;
}
private void UpdateText()
{
if (AssociatedObject == null) return;
if (string.IsNullOrEmpty(AssociatedObject.Text)) return;
string text = AssociatedObject.Text;
// Just incase we are not given text with elements.
string modifiedText = string.Format("<div>{0}</div>", text);
// reset the text because we will add to it.
AssociatedObject.Inlines.Clear();
try
{
var element = XElement.Parse(modifiedText);
ParseText(element, AssociatedObject.Inlines);
}
catch (Exception)
{
// if anything goes wrong just show the html
AssociatedObject.Text = text;
}
AssociatedObject.LayoutUpdated -= OnAssociatedObjectLayoutUpdated;
AssociatedObject.Loaded -= OnAssociatedObjectLoaded;
}
private static void ParseText(XElement element, InlineCollection inlines)
{
if (element == null) return;
InlineCollection currentInlines = inlines;
var elementName = element.Name.ToString().ToUpper();
switch (elementName)
{
case ElementA:
var link = new Hyperlink();
var href = element.Attribute("href");
if (href != null)
{
try
{
link.NavigateUri = new Uri(href.Value);
}
catch (System.FormatException) { /* href is not valid */ }
}
inlines.Add(link);
currentInlines = link.Inlines;
break;
case ElementB:
case ElementStrong:
var bold = new Bold();
inlines.Add(bold);
currentInlines = bold.Inlines;
break;
case ElementI:
case ElementEm:
var italic = new Italic();
inlines.Add(italic);
currentInlines = italic.Inlines;
break;
case ElementU:
var underline = new Underline();
inlines.Add(underline);
currentInlines = underline.Inlines;
break;
case ElementBr:
inlines.Add(new LineBreak());
break;
case ElementP:
// Add two line breaks, one for the current text and the second for the gap.
if (AddLineBreakIfNeeded(inlines))
{
inlines.Add(new LineBreak());
}
Span paragraphSpan = new Span();
inlines.Add(paragraphSpan);
currentInlines = paragraphSpan.Inlines;
break;
case ElementLi:
inlines.Add(new LineBreak());
inlines.Add(new Run { Text = " • " });
break;
case ElementUl:
case ElementDiv:
AddLineBreakIfNeeded(inlines);
Span divSpan = new Span();
inlines.Add(divSpan);
currentInlines = divSpan.Inlines;
break;
}
foreach (var node in element.Nodes())
{
XText textElement = node as XText;
if (textElement != null)
{
currentInlines.Add(new Run { Text = textElement.Value });
}
else
{
ParseText(node as XElement, currentInlines);
}
}
// Add newlines for paragraph tags
if (elementName == "ElementP")
{
currentInlines.Add(new LineBreak());
}
}
private static bool AddLineBreakIfNeeded(InlineCollection inlines)
{
if (inlines.Count > 0)
{
var lastInline = inlines[inlines.Count - 1];
while ((lastInline is Span))
{
var span = (Span)lastInline;
if (span.Inlines.Count > 0)
{
lastInline = span.Inlines[span.Inlines.Count - 1];
}
}
if (!(lastInline is LineBreak))
{
inlines.Add(new LineBreak());
return true;
}
}
return false;
}
}
然后,您可以将此行为添加到cusotm渲染器中的本Native Control
中。
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
HtmlTextBehavior behavior = new HtmlTextBehavior();
Interaction.GetBehaviors(Control).Add(behavior);
}
我已经上传了代码示例 。 请检查。
也许看看这个https://blog.pieeatingninjas.be/2017/11/05/creating-a-hyperlinklabel-in-xamarin-forms/ ...这可能是一个很好的起点还缺少您的需求吗?
当前,它仅支持超链接,但是处理标签的方式是相同的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.