I am using a couple of sources to make a custom renderer for a label that can display htmlstring and has data detectors. On android, it works perfectly, but ios implementation has some issues. Here's the ios implementation :
`using System.ComponentModel;
using CoreGraphics;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(HyperLinkLabel), typeof(HyperLinkLabelRenderer))]
namespace YourNameSpace
{
public class HyperLinkLabelRenderer : ViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs e)
{
base.OnElementChanged(e);
var view = (HyperLinkLabel)Element;
if (view == null) return;
var attr = new NSAttributedStringDocumentAttributes();
var nsError = new NSError();
attr.DocumentType = NSDocumentType.HTML;
var myHtmlData = NSData.FromString(view.Text, NSStringEncoding.Unicode);
UITextView uilabelleftside = new UITextView(new CGRect(0, 0, view.Width, view.Height));
//uilabelleftside.Text = view.Text;
uilabelleftside.Editable = false;
uilabelleftside.AttributedText = new NSAttributedString(myHtmlData, attr, ref nsError);
uilabelleftside.Font = UIFont.SystemFontOfSize((float)view.FontSize);
// Setting the data detector types mask to capture all types of link-able data
uilabelleftside.DataDetectorTypes = UIDataDetectorType.All;
uilabelleftside.BackgroundColor = UIColor.Clear;
// overriding Xamarin Forms Label and replace with our native control
SetNativeControl(uilabelleftside);
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Label.TextProperty.PropertyName)
{
var view = (HyperLinkLabel)Element;
if (view == null) return;
var attr = new NSAttributedStringDocumentAttributes();
var nsError = new NSError();
attr.DocumentType = NSDocumentType.HTML;
var myHtmlData = NSData.FromString(view.Text, NSStringEncoding.Unicode);
UITextView uilabelleftside = new UITextView(new CGRect(0, 0, view.Width, view.Height));
uilabelleftside.AttributedText = new NSAttributedString(myHtmlData, attr, ref nsError);
uilabelleftside.Font = UIFont.SystemFontOfSize((float)view.FontSize);
uilabelleftside.Editable = false;
// Setting the data detector types mask to capture all types of link-able data
uilabelleftside.DataDetectorTypes = UIDataDetectorType.All;
uilabelleftside.BackgroundColor = UIColor.Clear;
// overriding Xamarin Forms Label and replace with our native control
SetNativeControl(uilabelleftside);
}
}
}
}
`
When I scroll down or up and an item reappears, it fires OnElementChanged with different values and this causes the text of the renderer to overlap.
Here's my Xaml:
<TabbedPage.ItemTemplate> <DataTemplate> <ContentPage Title="{Binding title}"> <ListView ItemsSource="{Binding Posts}"> <ListView.RowHeight> <OnPlatform x:TypeArguments="x:Int32" iOS="200" Android="220"/> </ListView.RowHeight> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <Grid Padding="8"> <Grid.ColumnDefinitions> <ColumnDefinition Width = "50"/> <ColumnDefinition Width = "*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height = "40"/> <RowDefinition Height = "3"/> <RowDefinition Height = "*"/> <RowDefinition Height = "30"/> </Grid.RowDefinitions> <Image Grid.Column = "0" Grid.Row = "0" Source = "{Binding author.avatar_url}" Aspect = "AspectFill" WidthRequest = "40" HeightRequest = "40" HorizontalOptions = "Center" VerticalOptions = "Center"/> <Grid Grid.Column = "1"> <Grid.ColumnDefinitions> <ColumnDefinition Width = "*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height = "15"/> <RowDefinition> <OnPlatform x:TypeArguments = "GridLength" iOS="10" Android="15" /> </RowDefinition> </Grid.RowDefinitions> <Label Grid.Row = "0" Style = "{StaticResource authorName}" Text="{Binding author.full_name}" /> <Label Grid.Row = "1" Style = "{StaticResource proffInfo}" Text="{Binding author.proffInfo}" /> </Grid> <Grid x:Name = "postContent" Grid.Row = "2" Grid.Column = "0" Grid.ColumnSpan = "2" > <Grid.RowDefinitions> <RowDefinition Height = "30"/> <RowDefinition Height = "*"/> </Grid.RowDefinitions> <Label Grid.Row = "0 " Style = "{StaticResource heading1}" Text = "{Binding title}" /> <!--<WebView Grid.Row = "1"> <WebView.Source> <HtmlWebViewSource Html="{Binding html_content}"/> </WebView.Source> </WebView>--> <renderers:HyperLinkLabel Grid.Row = "1" Text="{Binding html_content}" /> </Grid> </Grid> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </ContentPage> </DataTemplate> </TabbedPage.ItemTemplate>
The xaml shouldn't be an issue cause it renders on android just fine.