2017-05-09 48 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