Ellipse only a section in a TextView

I was wondering if it is possible to cut only part of a string in a TextView. I would like to do the following:

Element with short title (X) Element with a very lo...(X) 

The name should be elliptical, but X should always be visible. In my case, it is impossible to use more than one TextView. Do you think there is an easy way to do this?

Thanks!

+6
android string textview abbreviation
source share
2 answers

I really needed a clean solution for the project, so after searching and searching for any solutions that I thought I liked, I spent some time writing this.

Here is a TextView implementation with improved ellipsis control. The way this works is to use the Android Spanned interface. It defines an enumeration that you can use to mark a specific section of text that you need to make an ellipsis, if necessary.

Limitations:

  • Does not support ellipsis on MIDDLE. This should be easy to add if it is really necessary (I did not).
  • This class will always display text on one line, since it only supports one line of text. Others can expand it if necessary (but it is much more complicated).

Here's a usage example:

FooActivity.java

 class FooActivity extends Activity { /** * You can do this however you'd like, this example uses this simple * helper function to create a text span tagged for ellipsizing */ CharSequence ellipsizeText(String text) { SpannableString s = new SpannableString(text); s.setSpan(TrimmedTextView.EllipsizeRange.ELLIPSIS_AT_END, 0, s.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); return s; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.foo_layout); TextView textView = (TextView) findViewById(R.id.textView4); SpannableStringBuilder text = new SpannableStringBuilder(); text.append(ellipsizeText("This is a long string of text which has important information ")); text.append("AT THE END"); textView.setText(text); } } 

Res / Layouts / foo_layout.xml

 <com.example.text.TrimmedTextView android:id="@+id/textView4" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge"/> 

What he

Here is an example of the result:

screenshot_of_example

Implementation

 package com.example.text; import android.content.Context; import android.text.Editable; import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextUtils; import android.text.TextUtils.TruncateAt; import android.text.TextWatcher; import android.util.AttributeSet; import android.util.Log; import android.widget.TextView; public class TrimmedTextView extends TextView { public static enum EllipsizeRange { ELLIPSIS_AT_START, ELLIPSIS_AT_END; } private CharSequence originalText; private SpannableStringBuilder builder = new SpannableStringBuilder(); /** * This allows the cached value of the original unmodified text to be * invalidated whenever set externally. */ private final TextWatcher textCacheInvalidator = new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { originalText = null; } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { } }; public TrimmedTextView(Context context) { this(context, null, 0); } public TrimmedTextView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TrimmedTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); addTextChangedListener(textCacheInvalidator); Log.v("TEXT", "Set!"); } /** * Make sure we return the original unmodified text value if it been * custom-ellipsized by us. */ public CharSequence getText() { if (originalText == null) { return super.getText(); } return originalText; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Layout layout = getLayout(); CharSequence text = layout.getText(); if (text instanceof Spanned) { Spanned spanned = (Spanned) text; int ellipsisStart; int ellipsisEnd; TruncateAt where = null; ellipsisStart = spanned.getSpanStart(EllipsizeRange.ELLIPSIS_AT_START); if (ellipsisStart >= 0) { where = TruncateAt.START; ellipsisEnd = spanned.getSpanEnd(EllipsizeRange.ELLIPSIS_AT_START); } else { ellipsisStart = spanned.getSpanStart(EllipsizeRange.ELLIPSIS_AT_END); if (ellipsisStart >= 0) { where = TruncateAt.END; ellipsisEnd = spanned.getSpanEnd(EllipsizeRange.ELLIPSIS_AT_END); } else { // No EllipsisRange spans in this text return; } } Log.v("TEXT", "ellipsisStart: " + ellipsisStart); Log.v("TEXT", "ellipsisEnd: " + ellipsisEnd); Log.v("TEXT", "where: " + where); builder.clear(); builder.append(text, 0, ellipsisStart).append(text, ellipsisEnd, text.length()); float consumed = Layout.getDesiredWidth(builder, layout.getPaint()); CharSequence ellipsisText = text.subSequence(ellipsisStart, ellipsisEnd); CharSequence ellipsizedText = TextUtils.ellipsize(ellipsisText, layout.getPaint(), layout.getWidth() - consumed, where); if (ellipsizedText.length() < ellipsisText.length()) { builder.clear(); builder.append(text, 0, ellipsisStart).append(ellipsizedText) .append(text, ellipsisEnd, text.length()); setText(builder); originalText = text; requestLayout(); invalidate(); } } } } 
+12
source share

You can try using something like this:

 myTextView.setEllipsize(TextUtils.TruncateAt.MIDDLE); 

This may not give you exactly what you want, but it may do something like this:

Element wi ... title (X)

reference Information

Truncateat
setEllipsize

+1
source share

All Articles