question

Cuong-3774 avatar image
0 Votes"
Cuong-3774 asked LeonLu-MSFT commented

Customized Ellipsis on Label of Xamarin Forms

Hello,
As the title says, I want to replace "..." with "...read more" when the label is truncated in Xamarin Forms.
Sorry for my bad english and I hope to get your help.
Thank you very much!

dotnet-xamarinforms
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

LeonLu-MSFT avatar image
0 Votes"
LeonLu-MSFT answered LeonLu-MSFT commented

Hello,​

Welcome to our Microsoft Q&A platform!

Do you want to achieve the result like following screenshot? click the ...Read More show the completely text. then click the read less, make the lable like previous type.

134173-image.png 134174-image.png

If so, you can create a custom contentview with two label.

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="App137.CustomLabel">
  <ContentView.Content>
        
            <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
                <Label x:Name="customLabel"   >
                </Label>
                <Label x:Name="lblReadMore" FontSize="18" FontAttributes="Bold"  >
                    <Label.GestureRecognizers>
                        <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
                    </Label.GestureRecognizers>
                </Label>
            </StackLayout>
      
    </ContentView.Content>
</ContentView>


Here is contentView's layout background code.

[XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CustomLabel : ContentView
    {
        public CustomLabel()
        {
            InitializeComponent();
        }

        #region Bindable Property
        public static readonly BindableProperty TextProperty = BindableProperty.Create(
            propertyName: nameof(TextProperty),
            returnType: typeof(string),
            declaringType: typeof(CustomLabel),
            defaultBindingMode: BindingMode.TwoWay,
            propertyChanged: TextPropertyChanged
            );

        public string Text
        {
            get { return (string)base.GetValue(TextProperty); }
            set { base.SetValue(TextProperty, value); }
        }

        //Show the read more label if word length > 100
        private static void TextPropertyChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var control = (CustomLabel)bindable;
            if (newValue != null)
            {
                control.lblReadMore.IsVisible = false;
                control.customLabel.Text = (string)newValue;
                var res=control.customLabel.Text.Split().Length;
                if (control.customLabel.Text.Split().Length > 30)
                {
                    control.ShortTextVisible = true;
                    control.ReadMoreLabel = true;
                }
            }
        }
        #endregion

        public bool ReadMoreLabel { get; set; }
        private bool _shortTextVisible;
        public bool ShortTextVisible
        {
            get => _shortTextVisible;
            set { _shortTextVisible = value; ShortTextPropertyChanged(); }
        }

        //By Default show first 30 words.
        private void ShortTextPropertyChanged()
        {
            if (Text != null)
            {
                if (ShortTextVisible)
                {
                    customLabel.Text = string.Join(" ", Text.Split().Take(30));
                    lblReadMore.Text = "...Read More";
                    lblReadMore.IsVisible = true;
                }
                else
                {
                    customLabel.Text = Text;
                    lblReadMore.Text = "Read Less";
                }
            }
        }
        private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
        {
            ShortTextVisible = !ShortTextVisible;
        }
    }


You can use it like following code,

<local:CustomLabel  Text="Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."    />



========================Update=========================

For Android, you can create a custom renderer for your Label. Get if Lable is ellipsized in the OnGlobalLayout method.

[assembly: ExportRenderer(typeof(Label), typeof(MyLabelRenderer))]
namespace App137.Droid
{
public class MyLabelRenderer: LabelRenderer
{
public MyLabelRenderer(Context context) : base(context)
{

     }
     protected override void OnElementChanged(ElementChangedEventArgs<Label> e)
     {
         base.OnElementChanged(e);

       TextView tv=  Control as TextView;
         CustomEllipsize(tv,3,"..ReadMore");
     }

     public void CustomEllipsize( TextView tv,  int maxLine,  String ellipsizetext)
     {

         if (tv.Tag == null)
         {
             tv.Tag=tv.Text;
         }
         ViewTreeObserver vto = tv.ViewTreeObserver;
         vto.AddOnGlobalLayoutListener(new OnGlobalLayoutListener(tv, maxLine, ellipsizetext)); 

}
}

 internal class OnGlobalLayoutListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener
 {
     public OnGlobalLayoutListener(TextView tv, int maxLine, string ellipsizetext)
     {
         Tv = tv;
         MaxLine = maxLine;
         Ellipsizetext = ellipsizetext;
     }

     public TextView Tv { get; }
     public int MaxLine { get; }
     public string Ellipsizetext { get; }

     public void OnGlobalLayout()
     {
         //throw new NotImplementedException();

         ViewTreeObserver obs = Tv.ViewTreeObserver;
         int lineEndIndex111 = Tv.Layout.GetLineEnd(0);
         obs.RemoveGlobalOnLayoutListener(this);

        Android.Text.Layout  l = Tv.Layout;
         if (l != null)
         {
             int lines = l.LineCount;
             if (lines > 0)
                 if (l.GetEllipsisCount(lines - 1) > 0)
                     Log.Debug("TAG", "Text is ellipsized");
         }

         if (MaxLine  <= 5)
         {
             int lineEndIndex = Tv.Layout.GetLineEnd(0);
             string text = Tv.Text.Substring(0, lineEndIndex - Ellipsizetext.Length)+ " " + Ellipsizetext;
             Tv.Text=text;
         }
         else if (Tv.LineCount >= MaxLine )
         {
             int lineEndIndex = Tv.Layout.GetLineEnd((MaxLine + 1) - 1);
             string text = Tv.Text.Substring(0, lineEndIndex - Ellipsizetext.Length) + " " + Ellipsizetext;
             Tv.Text = text;
         }
     }
 }```

```


Best Regards,

Leon Lu



If the response is helpful, please click "Accept Answer" and upvote it.

Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



image.png (30.6 KiB)
image.png (52.0 KiB)
· 7
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Thanks for your reply.
But I think show the first 30 words is not very good when running on devices with different resolutions, for example the last line may contain only 1-2 words.
Is there any way to know if the Label will be truncate?
If possible we can show/hide the "read more" label as needed.

0 Votes 0 ·

Is there any way to know if the Label will be truncate?

I
What is the value set by MaxLine? if the length of the text over the maxline*lineLength, Label will be truncated
0 Votes 0 ·

I set Maxline by 5, can you give me example code to know when Label will be truncated?

0 Votes 0 ·
Show more comments