TextView utilizando Spannable – ellipsize no funciona

El problema que intento solucionar es el siguiente: Tengo un TextView y estoy usando un Spannable para establecer algunos caracteres en negrita. El texto debe tener una máxima de 2 líneas ( android:maxLines="2" ) y quiero que el texto se elipse, pero por alguna razón no puedo hacer el texto ellipsized.

Aquí está el código simple:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:maxLines="2" android:ellipsize="end" android:bufferType="spannable" android:text="@string/app_name" android:textSize="15dp"/> </LinearLayout> 

Y la actividad:

 public class MyActivity extends Activity { private TextView name; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); name= (TextView) findViewById(R.id.name); name.setText("Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy "); Spannable spannable = (Spannable)name.getText(); StyleSpan boldSpan = new StyleSpan( Typeface.BOLD ); spannable.setSpan( boldSpan, 10, 15, Spannable.SPAN_INCLUSIVE_INCLUSIVE ); } } 

El texto se trunca, no se muestra "…". Introduzca aquí la descripción de la imagen

Tener el mismo problema y parece que los siguientes trabajos para mí:

 Spannable wordtoSpan = new SpannableString(lorem); wordtoSpan.setSpan(new ForegroundColorSpan(0xffff0000), 0, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); wordtoSpan.setSpan(new ForegroundColorSpan(0xff00ffff), 20, 35, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); textView.setText(wordtoSpan); 

En xml el textView tiene android:mutileLine conjunto, and android:ellipsize="end" , y android:singleLine="false ;

Me doy cuenta de que este es un post muy antiguo, pero viendo que todavía está sin respuesta y también me encontré con este problema hoy, pensé que publicaría una solución a esto. Espero que ayude a alguien en el futuro.

 ViewTreeObserver viewTreeObserver = textView.getViewTreeObserver(); viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { ViewTreeObserver viewTreeObserver = textView.getViewTreeObserver(); viewTreeObserver.removeOnGlobalLayoutListener(this); if (textView.getLineCount() > 5) { int endOfLastLine = textView.getLayout().getLineEnd(4); String newVal = textView.getText().subSequence(0, endOfLastLine - 3) + "..."; textView.setText(newVal); } } }); 

Tienes razón en que ellipsize, declarado en xml o en código no funcionará en texto spannable.

Sin embargo, con un poco de investigación que realmente puede hacer la elipsis usted mismo:

 private TextView name; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); name= (TextView) findViewById(R.id.name); String lorem = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy " name.setText(lorem); Spannable spannable = (Spannable)name.getText(); StyleSpan boldSpan = new StyleSpan(Typeface.BOLD); spannable.setSpan( boldSpan, 10, 15, Spannable.SPAN_INCLUSIVE_INCLUSIVE); int maxLines = 2; // in my experience, this needs to be called in code, your mileage may vary. name.setMaxLines(maxLines); // check line count.. this will actually be > than the # of visible lines // if it is long enough to be truncated if (name.getLineCount() > maxLines){ // this returns _1 past_ the index of the last character shown // on the indicated line. the lines are zero indexed, so the last // valid line is maxLines -1; int lastCharShown = name.getLayout().getLineVisibleEnd(maxLines - 1); // chop off some characters. this value is arbitrary, i chose 3 just // to be conservative. int numCharsToChop = 3; String truncatedText = lorem.substring(0, lastCharShown - numCharsToChop); // ellipsize! note ellipsis character. name.setText(truncatedText+"…"); // reapply the span, since the text has been changed. spannable.setSpan(boldSpan, 10, 15, Spannable.SPAN_INCLUSIVE_INCLUSIVE); } } 

Se trata de un problema conocido en el marco de Android: https://code.google.com/p/android/issues/detail?id=67186

Esto puede ser un pequeño truco mediante el uso de la reflexión para resolver este problema. Después de leer el código fuente de AOSP, en TextView.java, DynamicLayout sólo contiene un miembro de campo estático denominado sStaticLayout y está construido por el nuevo StaticLayout (nulo) sin ningún parámetro que incluya maxLines.

Por lo tanto, doEllipsis siempre será falso como mMaximumVisibleLineCount se establece Integer.MAX_VALUE de forma predeterminada.

 boolean firstLine = (j == 0); boolean currentLineIsTheLastVisibleOne = (j + 1 == mMaximumVisibleLineCount); boolean lastLine = currentLineIsTheLastVisibleOne || (end == bufEnd); ...... if (ellipsize != null) { // If there is only one line, then do any type of ellipsis except when it is MARQUEE // if there are multiple lines, just allow END ellipsis on the last line boolean forceEllipsis = moreChars && (mLineCount + 1 == mMaximumVisibleLineCount); boolean doEllipsis = (((mMaximumVisibleLineCount == 1 && moreChars) || (firstLine && !moreChars)) && ellipsize != TextUtils.TruncateAt.MARQUEE) || (!firstLine && (currentLineIsTheLastVisibleOne || !moreChars) && ellipsize == TextUtils.TruncateAt.END); if (doEllipsis) { calculateEllipsis(start, end, widths, widthStart, ellipsisWidth, ellipsize, j, textWidth, paint, forceEllipsis); } } 

Así que se extiende el TextView y hacer una vista llamada EllipsizeTextView

 public class EllipsizeTextView extends TextView { public EllipsizeTextView(Context context) { super(context); } public EllipsizeTextView(Context context, AttributeSet attrs) { super(context, attrs); } public EllipsizeTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); } public EllipsizeTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { StaticLayout layout = null; Field field = null; try { Field staticField = DynamicLayout.class.getDeclaredField("sStaticLayout"); staticField.setAccessible(true); layout = (StaticLayout) staticField.get(DynamicLayout.class); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } if (layout != null) { try { field = StaticLayout.class.getDeclaredField("mMaximumVisibleLineCount"); field.setAccessible(true); field.setInt(layout, getMaxLines()); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (layout != null && field != null) { try { field.setInt(layout, Integer.MAX_VALUE); } catch (IllegalAccessException e) { e.printStackTrace(); } } } 

}

¡problema resuelto!

Una solución sencilla y de trabajo

Este es mi código ->

 <TextView android:id="@+id/textViewProfileContent" android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="false" android:ellipsize="end" android:maxLines="3" android:textSize="14sp" android:textColor="#000000" /> SpannableStringBuilder sb = new SpannableStringBuilder(); SpannableString attrAdditional = new SpannableString(additionalText); attrAdditional.SetSpan(new StyleSpan(TypefaceStyle.Bold), 0, additionalText.Length, 0);... sb.Append(attrAdditional);... ProfileContent.SetText(sb, **TextView.BufferType.Normal**); 

Resultado

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.