我有一个自定义渲染器,可以在UITextView中显示HTML格式的文本。如果我将文本硬编码到包含控件的页面的构造函数中(因此它在自定义控件的OnElementChanged事件中设置),它显示正常。如果我等待api调用以获取文本然后设置它(因此它在自定义控件的OnElementPropertyChanged事件中设置)它不会重新绘制。如果我更改设备的方向,则会显示文本。我需要添加什么才能让它在设置时显示文字?
[assembly: ExportRenderer(typeof(HtmlLabel), typeof(HtmlLabelRenderer))]
namespace MyApp.iOS.Renderers
{
class HtmlLabelRenderer : ViewRenderer<HtmlLabel, UITextView>
{
private UITextView _htmlTextView = new UITextView();
protected override void OnElementChanged(ElementChangedEventArgs<HtmlLabel> e)
{
base.OnElementChanged(e);
if (Element?.Text == null) return;
SetHtmlText(Element.Text);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (string.Equals(e.PropertyName, "Text", StringComparison.CurrentCultureIgnoreCase))
{
SetHtmlText(((HtmlLabel)sender).Text);
_htmlTextView.SetNeedsDisplay();
}
base.OnElementPropertyChanged(sender, e);
}
private void SetHtmlText(string text)
{
var attr = new NSAttributedStringDocumentAttributes {DocumentType = NSDocumentType.HTML};
var nsError = new NSError();
_htmlTextView.Editable = false;
_htmlTextView.AttributedText = new NSAttributedString(text, attr, ref nsError);
_htmlTextView.DataDetectorTypes = UIDataDetectorType.All;
SetNativeControl(_htmlTextView);
}
}
}
更新:通过将OnElementChanged更改为:
,我得到了进一步的发展 protected override void OnElementChanged(ElementChangedEventArgs<HtmlLabel> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null) return;
SetHtmlText(e.NewElement.Text ?? string.Empty);
SetNativeControl(_htmlTextView);
}
现在,如果我在页面上有多个HtmlLabel,则显示除第一个之外的所有HtmlLabel。
答案 0 :(得分:0)
尝试更改:
_htmlTextView.SetNeedsDisplay();
到
SetNeedsDisplay();
或,
(Control ?? NativeView).SetNeedsDisplay();
答案 1 :(得分:0)
您的自定义HtmlLabel类应该能够在Android和iOS上从同一个东西派生
namespace YourNameSpace
{
public class HtmlLabel : Label
{
}
}
Android的渲染器看起来应该是这样的
[assembly: ExportRenderer(typeof(HtmlLabel), typeof(HtmlLabelRenderer))]
namespace YourNameSpace.Droid
{
public class HtmlLabelRenderer : ViewRenderer<Label, TextView>
{
TextView _textView;
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Element == null)
return;
if(Control == null)
{
_textView = new TextView(Context);
SetHtmlText(Element.Text);
SetNativeControl(_textView);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (Element == null || Control == null)
return;
if (e.PropertyName == HtmlLabel.TextProperty.PropertyName)
{
SetHtmlText(Element.Text);
}
}
private void SetHtmlText(string text)
{
if (Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.N)
{
_textView.TextFormatted = Html.FromHtml(text, Android.Text.FromHtmlOptions.ModeCompact);
}
else
{
_textView.TextFormatted = Html.FromHtml(text);
}
}
}
}
在iOS上它应该看起来非常相似
[assembly: ExportRenderer(typeof(HtmlLabel), typeof(HtmlLabelRenderer))]
namespace YourNameSpace.iOS
{
public class HtmlLabelRenderer : ViewRenderer<Label, UITextView>
{
UITextView _textView;
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
if (Element == null)
return;
if(Control == null)
{
_textView = new UITextView();
SetHtmlText(Element.Text);
SetNativeControl(_textView);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (Element == null || Control == null)
return;
if (e.PropertyName == HtmlLabel.TextProperty.PropertyName)
{
SetHtmlText(Element.Text);
}
}
private void SetHtmlText(string text)
{
var attr = new NSAttributedStringDocumentAttributes { DocumentType = NSDocumentType.HTML };
var nsError = new NSError();
_textView.Editable = false;
_textView.AttributedText = new NSAttributedString(text, attr, ref nsError);
_textView.DataDetectorTypes = UIDataDetectorType.All;
}
}
}
我在Android上测试了它并且它工作正常,当文本发生变化时调用OnElementPropertyChanged。但是,我没有在家里使用Mac来试用iOS渲染器,所以我只是假设它的功能几乎相同。
答案 2 :(得分:0)
Sharada Gururaj是对的,改编自源自编辑的iOS工作..但打破了Android。虽然这看起来很蛮力,但我使用条件编译来使它工作......
namespace MyApp.Renderers
{
#if __IOS__
public class HtmlLabel : Editor
{
}
#else
public class HtmlLabel : Label
{
}
#endif
}
这是android
[assembly: ExportRenderer(typeof(HtmlLabel), typeof(HtmlLabelRenderer))]
namespace MyApp.Droid.Renderers
{
public class HtmlLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
var view = (HtmlLabel)Element;
if (view?.Text == null) return;
SetHtmlText(view.Text);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Label.TextProperty.PropertyName)
{
SetHtmlText(((HtmlLabel) sender).Text);
}
}
private void SetHtmlText(string text)
{
var encodedText = (((int)Build.VERSION.SdkInt) >= 24) ? Html.FromHtml(text, FromHtmlOptions.ModeLegacy) :
#pragma warning disable 618
// need this for backward compatability
Html.FromHtml(text);
#pragma warning restore 618
Control.MovementMethod = LinkMovementMethod.Instance;
Control.SetText(encodedText, TextView.BufferType.Spannable);
}
}
}