Have you ever wanted to create a Label that could automatically detect HTTP Web Links ? or Phone number text ? or EMail address text ? and enable clickable action only on top of those links in the Label ? 😉
Well it’s a very common scenario in Mobile Apps development, if you had experienced it already, you know its very easy in Native app development. But when it comes to Xamarin Forms, oh well it’s a different story, whereas people almost end up trying to implement a WebView control instead of the Label and complicate the whole situation. lol 😀 (Yes I have been there too) Well XFLabs have a clickable Label control, but who on earth would want to make an entire Label control clickable only for a specific set of text like an email address inside a label, unless your intension is to fill the whole label with the email address only. 😛
Anyhow there was this one time I wanted to create a Label which automatically detect HTTP Web URLs, Phone Number text, Email Address text and enables clickable actions only on top of those specific types of text.
Solution ?
Well if it’s impossible to do it in Xamarin Forms, of course we need to praise the Custom Renderers, just like I did in my scenario. So here goes my solution. We are going to create a Custom Control in Xamarin Forms, which is going to be overridden in native Level and adjust the control to our needs. And I’m gonna call it the “AwesomeHyperLinkLabel”
PCL Implementation
So as usual, we create a custom control based on the Xamarin Forms Label as shown below…
namespace WhateverYourNamespace { /// <summary> /// Automatically detects the Phone numbers, web links and email addresses /// and make them clickable to be opened up in default device applications /// </summary> public class AwesomeHyperLinkLabel : Label { } }
Android Implementation
In Android we have the option property in default TextView called AutoLinkMask , which allows us to automatically set the TextView to detect and highlight all kinds of URLs, Phone Numbers, and EMail addresses.
[assembly: ExportRenderer(typeof(AwesomeHyperLinkLabel), typeof(AwesomeHyperLinkLabelRenderer))] namespace WhateverYourNamespace { public class AwesomeHyperLinkLabelRenderer : LabelRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Label> e) { base.OnElementChanged(e); var view = (AwesomeHyperLinkLabel)Element; if (view == null) return; TextView textView = new TextView(Forms.Context); textView.LayoutParameters = new LayoutParams(LayoutParams.WrapContent, LayoutParams.WrapContent); textView.SetTextColor(view.TextColor.ToAndroid()); // Setting the auto link mask to capture all types of link-able data textView.AutoLinkMask = MatchOptions.All; // Make sure to set text after setting the mask textView.Text = view.Text; textView.SetTextSize(ComplexUnitType.Dip, (float)view.FontSize); // overriding Xamarin Forms Label and replace with our native control SetNativeControl(textView); } } }
So as you can see above I have overridden the Xamarin Forms control with our native TextView control. Make sure to set text after setting the AutoLinkMask, otherwise the link-able text would not be detected by the TextView. Also keep in mind here you could define specifically what types of link-able data you need the Label to detect based on your requirements. 😉 but above example I have set it to all.
iOS Implementation
Also in iOS, we could use DataDetectorTypes property on UITextView which allows us to do the same as above, but keep in mind in Xamarin iOS UILabel is the equivalent of Xamarin Forms Label, but UILabel doesn’t have such properties to support our scenario. So we have to move to the native UITextView control.
It’s very important to keep in mind due to the above reasons we cannot derive this Custom Renderer from the usual LabelRenderer, we need to use the common ViewRenderer.
[assembly: ExportRenderer(typeof(AwesomeHyperLinkLabel), typeof(AwesomeHyperLinkLabelRenderer))] namespace WhateverYourNamespace { public class AwesomeHyperLinkLabelRenderer : ViewRenderer { protected override void OnElementChanged(ElementChangedEventArgs<View> e) { base.OnElementChanged(e); var view = (AwesomeHyperLinkLabel)Element; if (view == null) return; UITextView uilabelleftside = new UITextView(new CGRect(0, 0, view.Width, view.Height)); uilabelleftside.Text = view.Text; 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); } } }
So as you can see above we are setting the DataDetectorTypes property in UITextView to allow the control to highlight the link-able data. Also specially note that we are using ViewRenderer and overriding the Xamarin Forms Label with UITextView control.
That is why we have disabled the Editable property above and we are doing our best for this control to behave as a Label.
Let’s try it out!
Too bored to try it out yourself ? 😛 Yeah thought so. lol Anyways here’s a sample code where you could try out my AwesomeHyperLinkLabel.
public App() { // The root page of your application MainPage = new ContentPage { Content = new StackLayout { VerticalOptions = LayoutOptions.Center, Padding = new Thickness(10, 0, 10, 0), Children = { new Label { Text = "Hello! This is normal Label!" }, new AwesomeHyperLinkLabel { Text = "Hello! This is the AwesomeHyperLinkLabel by ÇøŋfuzëÐ SøurcëÇødë ! \n\nClick here www.confuzed-sourcecode.com and phone number : +65 9215 7231 and email address : udara.blahblah@blah.com" }, } } }; }
Very well, there you go fellas, now hit F5 and run that thing… 😉
TADAAAA!
WOOT WOOT ! Here how it is in iOS and Android ! 😀
Cheers!
Stay awesome fellas! 🙂