Reputation: 4230
Isn't there anything like a LinkButton in Xamarin?
I want to create a label with the looks of an url link that once tapped opens the external browser.
I also need to know how to open the device's external browser (to open an specified url) in a Portable Project.
Thanks
Upvotes: 12
Views: 10175
Reputation: 641
For Xamarin.Forms 3.2 and above
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding Url, Mode=OneWay}" TextColor="Blue">
<Span.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding TapCommand, Mode=OneWay}"
CommandParameter="https://www.xamarin.com"/>
</Span.GestureRecognizers>
</Span>
</FormattedString>
</Label.FormattedText>
</Label>
You may use commands with or without parameters, or just the tapped event.
Example :
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Xamarin" TextColor="Blue">
<Span.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding TapCommand, Mode=OneWay}"
CommandParameter="https://www.xamarin.com"/>
</Span.GestureRecognizers>
</Span>
</FormattedString>
</Label.FormattedText>
</Label>
in the ViewModel :
private ICommand _tapCommand;
public ICommand TapCommand =>
_tapCommand ?? (_tapCommand = new Command<string>(OpenUrl));
void OpenUrl(string url)
{
Device.OpenUri(new Uri(url));
}
Upvotes: 0
Reputation: 61
Create a label that can display underlined (or use Xamarin Forms Labs ExtendedLabel):
using Xamarin.Forms;
public class ExtendedLabel : Label
{
public static readonly BindableProperty IsUnderlinedProperty = BindableProperty.Create<ExtendedLabel, bool>(p => p.IsUnderlined, false);
public bool IsUnderlined
{
get { return (bool)GetValue(IsUnderlinedProperty); }
set { SetValue(IsUnderlinedProperty, value); }
}
// ...other custom properties
}
Handle the IsUnderlined property in your custom renderers:
public class ExtendedLabelRenderer : LabelRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
{
base.OnElementChanged(e);
// ...
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == ExtendedLabel.IsUnderlinedProperty.PropertyName)
{
RefreshControl(Control);
}
}
private void RefreshControl(UILabel control)
{
if (control == null) return;
// Apply based on IsUnderlined property
if (!string.IsNullOrEmpty(control.Text)) control.AttributedText = new NSMutableAttributedString(control.Text, underlineStyle: view.IsUnderlined ? NSUnderlineStyle.Single : NSUnderlineStyle.None);
// ...apply based on other custom properties
}
}
Add your label control to YourPage.xaml and add a gesture recognizer to handle tap:
<controls:ExtendedLabel
Text="View in browser"
TextColor="Blue"
IsUnderlined="True">
<controls:ExtendedLabel.GestureRecognizers>
<!--TODO:<TapGestureRecognizer Command="TapCommand" /> Couldn't do this for some reason so use Tapped handler-->
<TapGestureRecognizer
Tapped="OnOpenInBrowserTapGestureRecognizerTapped"
NumberOfTapsRequired="1" />
</controls:ExtendedLabel.GestureRecognizers>
</controls:ExtendedLabel>
Handle the tap in code behind YourPage.xaml.cs:
private void OnOpenInBrowserTapGestureRecognizerTapped(object sender, EventArgs args)
{
var labelViewSender = (ExtendedLabel)sender;
labelViewSender.Opacity = 0.6;
labelViewSender.FadeTo(1);
var viewModel = BindingContext as YourPageViewModel;
if (viewModel == null) return;
if (viewModel.NavigateToUrlCommand.CanExecute(null)) viewModel.NavigateToUrlCommand.Execute(null);
}
The view model:
public class YourPageViewModel : ViewModelBase
{
public const string NavigateToUrlMessage = "NavigateToUrl";
private string _url;
public string Url
{
get { return _url; }
set { SetProperty(ref _url, value); }
}
//...
private Command _navigateToUrlCommand;
public ICommand NavigateToUrlCommand
{
get { return _navigateToUrlCommand ?? (_navigateToUrlCommand = new Command(param => NavigateToUrl(), CanNavigateToUrl)); }
}
public bool CanNavigateToUrl(object parameter) => true;
private void NavigateToUrl()
{
MessagingCenter.Send(this, NavigateToUrlMessage, Url);
}
//...
}
Subscribe to and handle the NavigateToUrlMessage message in the YourPage.xaml.cs code behind:
protected override void OnAppearing()
{
MessagingCenter.Subscribe<YourPageViewModel, string>(this, YourPageViewModel.NavigateToUrlMessage, (sender, args) =>
{
var context = (BindingContext as YourPageViewModel);
if (context == null) return;
if (string.IsNullOrEmpty(args)) return;
Device.BeginInvokeOnMainThread(() =>
{
Device.OpenUri(new Uri(args));
});
});
//...
base.OnAppearing();
}
protected override void OnDisappearing()
{
MessagingCenter.Unsubscribe<YourPageViewModel, string>(this, YourPageViewModel.NavigateToUrlMessage);
//...
base.OnDisappearing();
}
Upvotes: 2
Reputation: 74209
The Xamarin.Forms
way to open an URL string in the default mobile browser:
Device.OpenUri(new Uri("http://example.com"))
While a Forms' Label
does not have a click event, you can add a TapGestureRecognizer
so when the label is tapped it executes Device.OpenUri
.
var myURLLabel = new Label
{
Text = "https://xamarin.com"
};
myURLLabel.GestureRecognizers.Add(new TapGestureRecognizer
{
Command = new Command(() => {
Device.OpenUri(new Uri(myURLLabel.Text));
})
});
Xamarin-Forms-Labs' ExtendedLabel
allows you style a label's text as underlined....
Ref: https://github.com/XLabs/Xamarin-Forms-Labs/wiki/ExtendedLabel
Upvotes: 11