2017-05-09 108 views
0

我有一个自定义的渲染器在UITextView中显示HTML格式的文本。如果我将文本硬编码到包含控件的页面的构造函数中(因此它被设置在自定义控件的OnElementChanged事件中),它显示正常。如果我等待一个api调用来获取文本,然后设置它(所以它被设置在自定义控件的OnElementPropertyChanged事件中),它不会重绘。如果我更改设备的方向,则会显示文本。我需要添加什么才能让它在设置时显示文本?Xamarin Forms iOS CustomRenderer不重绘

[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); 
     } 
    } 
} 

更新:现在

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页面上的所有除第一个显示:我得到了进一步通过改变OnElementChanged来。

回答

0

尝试改变从:

_htmlTextView.SetNeedsDisplay(); 

SetNeedsDisplay(); 

,或者

(Control ?? NativeView).SetNeedsDisplay(); 
+0

我试过了,没有效果 – Christine

+0

好 - 只是为了确认,是' 'HtmlLabel'上的Text属性是一个可绑定的属性?如果可以,可以发布'HtmlLabel'的代码。 – Ada

+0

没有,是HtmlLabel无码 - 公共类HtmlLabel:标签 { } 我把它添加到页面 然后在检索到代码后设置代码中的文本 HtmlDescription.Text = announcement.Details; – Christine

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渲染器,所以我只是假设它的功能几乎相同。

+0

我试过了,没有效果 – Christine

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); 
     } 
    } 
} 
+0

我更新了我的答案,你应该能够在两个平台上从相同的东西中派生出来,并使用'ViewRenderer ' – Nick