2010-07-12 22 views
6

Me preguntaba si es posible abreviar solo una parte de una cadena en un TextView. Lo que me gustaría hacer es algo como esto:Ellipsize solo una sección en un TextView

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

El título debe ser ellipsized, pero el X debe ser siempre visible. En mi caso, no es posible usar más de un TextView. ¿Crees que hay una manera simple de hacer esto?

Gracias!

Respuesta

1

Usted puede intentar usar algo como esto:

myTextView.setEllipsize(TextUtils.TruncateAt.MIDDLE); 

Puede que no te dará exactamente lo que quiere sin embargo, puede hacer algo como esto:

Elemento wi ... Título (X)

Información de Referencia

TruncateAt
setEllipsize

+0

Gracias por su respuesta! No es una mala solución, pero no es exactamente lo que estaba buscando ... – Antonio

+0

Más allá de esto, tendrá que crear sus propios cheques y dibujarlo usted mismo con los puntos suspensivos donde lo desee. –

12

realmente necesitaba una solución limpia para un proyecto así que después de buscar alrededor y no encontrar ninguna solución que sentía me ha gustado, me tomó un tiempo para escribir esto.

Aquí hay una implementación de un TextView con control de puntos suspensivos mejorado. La forma en que funciona es mediante el uso de la interfaz extendida de Android. Define una enumeración que puede usar para etiquetar la sección específica del texto que le gustaría que se elipsifique si es necesario.

Limitaciones:

  • no admite puntos suspensivos en el medio. Esto debería ser fácil de agregar si es realmente necesario (no lo hice).
  • Esta clase siempre representará el texto en una línea, ya que solo admite una sola línea de texto. Otros pueden extenderlo si es necesario (pero es un problema mucho más difícil).

He aquí una muestra del uso:

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

Eso es todo

He aquí un ejemplo del resultado:

screenshot_of_example

la implementación

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's 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(); 
     } 
    } 
    } 
} 
+2

No tuve mucho éxito con esto hasta que cambié layout.getWidth() a getMeasuredWidth(). Dependiendo del diseño en que se encuentre su TextView, esto podría ayudarlo. – denizmveli

Cuestiones relacionadas