Tuesday, 30 October 2018

Creating a Hyperlink in Xamarin.Forms II

Previously, I wrote about creating a hyperlink in a Xamarin.Forms app by adding a TapGestureRecognizer to the GestureRecognizers collection of a Span, and setting its TextDecorations property to Underline. This can be achieved in XAML as follows:

<Span Text="Xamarin documentation" TextColor="Blue" TextDecorations="Underline"> <Span.GestureRecognizers> <TapGestureRecognizer Command="{Binding TapCommand}" CommandParameter="https://docs.microsoft.com/xamarin/" /> </Span.GestureRecognizers> </Span>

The problem with this approach is that it requires repetitive code every time you need a hyperlink in your app. A better approach would be to sub-class the Span class into a HyperlinkSpan class, with the gesture recognizer and text decoration added there. Unfortunately, the Span class is sealed and so can’t be inherited from. However, there’s an enhancement proposal to unseal the class, so that it can be inherited from. Go and up vote it here!

Therefore, for the purposes of this blog post I’ll demonstrate sub-classing the Label class to create a HyperlinkLabel class. Once the Span class is unsealed, the same approach can be followed.

The sample this code comes from can be found on GitHub.

Creating a HyperlinkLabel Class

The following code shows the HyperlinkLabel class:

public class HyperlinkLabel : Label { public static readonly BindableProperty UrlProperty = BindableProperty.Create(nameof(Url), typeof(string), typeof(HyperlinkLabel), null); public string Url { get { return (string)GetValue(UrlProperty); } set { SetValue(UrlProperty, value); } } public HyperlinkLabel() { TextDecorations = TextDecorations.Underline; TextColor = Color.Blue; GestureRecognizers.Add(new TapGestureRecognizer { Command = new Command(() => Device.OpenUri(new Uri(Url))) }); } }

The class defines a Url property (and BindableProperty), and the class constructor sets the hyperlink look and the TapGestureRecognizer that will respond when the hyperlink is tapped. When a HyperlinkLabel is tapped, the TapGestureRecognizer will respond by executing the Device.OpenUri method to open the URL, specified by the Url property, in a web browser.

The HyperlinkLabel class can be consumed simply by adding an XML namespace declaration to your XAML, and then an instance of the class:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:HyperlinkLabel" x:Class="HyperlinkLabel.MainPage"> <StackLayout Margin="20"> <Label Text="Hyperlink Demo" HorizontalOptions="Center" FontAttributes="Bold" /> <Label Text="Click the text below to view Xamarin documentation." /> <local:HyperlinkLabel Text="Xamarin Documentation" Url="https://docs.microsoft.com/xamarin/" HorizontalOptions="Center" /> </StackLayout> </ContentPage>

The HyperlinkLabel instance is rendered as follows:

Simulator Screen Shot - iPhone 8 - 2018-10-29 at 11.37.55

It’s Url property is set to the URL to be opened when the hyperlink is tapped. When this occurs, a web browser appears and the URL is navigated to:

Simulator Screen Shot - iPhone 8 - 2018-10-29 at 11.38.04


Summary

The repetitive code for creating a hyperlink on a Span or Label should be sub-classed into a HyperlinkSpan or HyperlinkLabel class, with the gesture recognizer and text decoration added there. Unfortunately, the Span class is sealed and currently can’t be inherited from. However, there’s an enhancement proposal to unseal the Span class. Once this is achieved, the approach taken in this blog post for the HyperlinkLabel class can be applied to the Span class.

The sample this code comes from can be found on GitHub.

No comments:

Post a Comment