keertana
keertana

Reputation: 121

how to draw a line on label text in xamarin forms

As shown in the image below I need to draw a line dynamically on a label text. Here is my label in listview

enter image description here

Can anyone please tell me about this?

Upvotes: 7

Views: 7185

Answers (6)

nzrytmn
nzrytmn

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

Subhan Ali
Subhan Ali

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

alejosoft
alejosoft

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

Ziyad Godil
Ziyad Godil

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

Ahmad ElMadi
Ahmad ElMadi

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

Timo Salom&#228;ki
Timo Salom&#228;ki

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.

  1. On Android, you STRIKE_THRU_TEXT_FLAG on the TextView. You need something like this in the custom renderer: someTextView.PaintFlags = Paint.StrikeThruText;
  2. On iOS, you should follow the guidance from this thread on Xamarin forums. Basically, you use UIStringAttributes to achieve the desired results.

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

Related Questions