[英]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.