Reputation: 121
As shown in the image below I need to draw a line dynamically on a label text. Here is my label in listview
Can anyone please tell me about this?
Upvotes: 7
Views: 7185
Reputation: 6911
Text decorations property do this easily. you just have to set this property.
<Label Text="This is text with strikethrough." TextDecorations="Strikethrough" />
But if you want to this dynamically during the runtime than you have to binding this property.
There is a IValueConverter interface at xamarin that you can use for this. You can create a converter like below:
public class StatusToTextDecoration : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var decorationText = TextDecorations.None;
if (value == null) return decorationText;
if (System.Convert.ToInt32(value) == MyStatus) decorationText = TextDecorations.Strikethrough;
return decorationText;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
//For this case you can ignore this
return null;
}
}
and than just you have to add this converter to your xaml page as reference:
xmlns:converterLocal="clr-namespace:MyApp.Converter;assembly=MyApp"
and set as a resource at top of your page after references:
<ContentPage.Resources>
<converterLocal:StatusToTextDecoration x:Key="StatusToTextDecoration"/>
</ContentPage.Resources>
And here you go , just set your converter at your label than :
<Label Text="This is text with strikethrough." TextDecorations="{Binding MyStateId, Converter={StaticResource StatusToTextDecoration}}" />
than it will set text decoration according the valur of your "MyStateId" field at data source.
Upvotes: 1
Reputation: 1430
I think rather than implementing it with different layouts or box view we can simply use TextDecorations property for Label provided by Xamarin like below.
<Label
Text="$200"
TextDecorations="Strikethrough" />
Upvotes: 9
Reputation: 186
I'm adding my Android side implementation to this answer. I adapted it from this article: https://smstuebe.de/2016/08/29/underlinedlabel.xamarin.forms/
using Android.Graphics;
using Android.Widget;
using MyNamespace.Core.CustomRenderers;
using MyNamespace.Droid.Library.ViewRenderers;
using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ResolutionGroupName(StrikethroughEffect.EffectNamespace)]
[assembly: ExportEffect(typeof(StrikethroughEffectAndroid), nameof(StrikethroughEffect))]
namespace MyNamespace.Droid.Library.ViewRenderers
{
public class StrikethroughEffectAndroid : PlatformEffect
{
protected override void OnAttached()
{
RenderEffect(true);
}
protected override void OnDetached()
{
RenderEffect(false);
}
protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
{
base.OnElementPropertyChanged(args);
if (args.PropertyName == Label.TextProperty.PropertyName || args.PropertyName == Label.FormattedTextProperty.PropertyName)
{
RenderEffect(true);
}
}
private void RenderEffect(bool shouldApply)
{
try
{
var textView = (TextView)Control;
if (shouldApply)
{
textView.PaintFlags |= PaintFlags.StrikeThruText;
}
else
{
textView.PaintFlags &= ~PaintFlags.StrikeThruText;
}
}
catch (Exception ex)
{
Console.WriteLine("Cannot strike-through Label. Error: ", ex.Message);
}
}
}
}
Cheers!
Upvotes: 0
Reputation: 2680
It's very simple to use Effect do following steps:
Xaml
<Label Text="{Binding TotalReatilAmount}" >
<Label.Effects>
<Helpers:LineThroughEffect />
</Label.Effects>
</Label>
Don't forget to put below line in XAML header
xmlns:Helpers="clr-namespace:MyNameSpace.Helpers"
Create one class inheriting from RoutingEffect
public class LineThroughEffect : RoutingEffect
{
public LineThroughEffect() : base("MyNameSpace.Helpers.PlatformLineThroughEffect") { }
}
Create render for Platform Specific
iOS
[assembly: ResolutionGroupName("MyNameSpace.Helpers")]
[assembly: ExportEffect(typeof(PlatformLineThroughEffect), nameof(PlatformLineThroughEffect))]
namespace MyNameSpace.iOS.Renderers
{
public class PlatformLineThroughEffect : PlatformEffect
{
protected override void OnAttached()
{
SetUnderline(true);
}
protected override void OnDetached()
{
SetUnderline(false);
}
protected override void OnElementPropertyChanged(System.ComponentModel.PropertyChangedEventArgs args)
{
base.OnElementPropertyChanged(args);
if (args.PropertyName == Label.TextProperty.PropertyName ||
args.PropertyName == Label.FormattedTextProperty.PropertyName)
{
SetUnderline(true);
}
}
private void SetUnderline(bool underlined)
{
try
{
var label = (UILabel)Control;
if (label != null)
{
var text = (NSMutableAttributedString)label.AttributedText;
if (text != null)
{
var range = new NSRange(0, text.Length);
if (underlined)
{
text.AddAttribute(UIStringAttributeKey.StrikethroughStyle,
NSNumber.FromInt32((int)NSUnderlineStyle.Single), range);
}
else
{
text.RemoveAttribute(UIStringAttributeKey.StrikethroughStyle, range);
}
}
}
}
catch (Exception ex)
{
ex.Track();
}
}
}
}
Upvotes: 4
Reputation: 2617
Here you go, you can make your own control (strikedLabel) and place this code. To make it more fun and flexiable you can add bindable properties like (IsStriked, StrikeColor, etc...) , remember that order between the label and the BoxView is important
<Grid>
<Label VerticalOptions="Center" Text="Sample string" />
<BoxView HeightRequest="3"
VerticalOptions="Center"
Opacity="0.5"
Color="Aqua" />
</Grid>
Upvotes: 9
Reputation: 7189
Since Xamarin.Forms doesn't provide this functionality out of the box, you'll need to extend the Label by creating a custom renderer for each platform. By doing that you can access the native controls on each platform(TextView on Android and UILabel on iOS) and implement the strikethrough effect there.
someTextView.PaintFlags = Paint.StrikeThruText;
If you're new to custom renderers, take a look at the getting started tutorial on how to customize the Entry control here.
Edit: Actually, you might even be able to pull this off using an Effect. More information here.
Upvotes: 4