简体   繁体   中英

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

在此输入图像描述

Can anyone please tell me about this?

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>

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 .

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();
            }
        }
    }
}

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" />

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM