2013-02-04 7 views
12

Das Problem, das ich beheben möchte, ist das Folgende: Ich habe eine TextView und ich verwende eine Spannable, um einige Zeichen fett zu setzen. Der Text muss eine Maxime von 2 Zeilen haben (android:maxLines="2") und ich möchte, dass der Text ellipsentiert wird, aber aus irgendeinem Grund kann ich den Text nicht ellipsenförmig machen.TextView mit Spannable - Ellipsize funktioniert nicht

Hier ist der einfache Code ist:

<?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> 

und die Aktivität:

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

    } 
} 

Der Text wird abgeschnitten, kein "..." angezeigt. enter image description here

Antwort

4

Sie haben Recht in dieser Ellipse, deklariert entweder in XML oder in Code wird nicht auf übersetzbaren Text funktionieren.

Doch mit ein wenig Untersuchung Sie tatsächlich tun können, die ellipsizing selbst:

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

} 
9

gleiche Problem und scheint die folgenden Werke für mich zu haben:

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

in xml die Textview hat android:mutileLine eingestellt und android:ellipsize="end" und android:singleLine="false;

+4

Sie mir angedeutet, war ich mit 'textView.setText (spannableStringBuilder, TextView.BufferType.SPANNABLE)'. Verwenden Sie einfach 'textView.setText (spannableStringBuilder)' und es funktioniert. – Sylphe

+0

@lannyf wie funktioniert das? Hast du das gleiche Problem wie die OP? Ich tue und das funktioniert nicht für mich –

+0

@Sylphe Irgendeine Idee, warum dieser Puffertyp es brach? – AdamMc331

10

Ich weiß, dass dies ein sehr alter Beitrag ist, aber da es immer noch unbeantwortet ist und ich dieses Problem heute noch hatte, dachte ich mir, ich würde eine Lösung dafür posten. Hoffentlich hilft es jemandem in der Zukunft.

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); 
     } 
    } 
}); 
+0

es funktionierte für mich – kot331107

+0

aber Sie haben es als eine mögliche Lösung gepostet :) – kot331107

2

Dies kann ein kleiner Trick, durch Reflexion mit diesem Problem zu lösen. Nach dem Lesen des Quellcodes von AOSP, in TextView.java, enthält DynamicLayout nur ein statisches Feldelement mit dem Namen sStaticLayout und es wird durch neues StaticLayout (null) ohne Parameter wie maxLines erstellt.

Daher ist doEllipsis immer falsch, da mMaximumVisibleLineCount standardmäßig auf Integer.MAX_VALUE gesetzt ist.

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

So erstreckt ich die Textview und einen Blick 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(); 
     } 
    } 
} 

}

Problem gelöst Namen machen!

0

Eine einfache und funktionierende Lösung

Dies ist mein Code ->

<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**); 

Result

0

enter image description here

https://github.com/lsjwzh/FastTextView haben eine saubere Lösung für dieses. Sie sollten zuerst die überspannte Schnur Wrapper, dann außer Kraft setzen getSpans, getSpanStart, getSpanEnd ... https://github.com/lsjwzh/FastTextView/blob/master/widget.FastTextView/src/main/java/android/text/EllipsisSpannedContainer.java

Linie 207 zeigen Ihnen, wie zu verwenden. https://github.com/lsjwzh/FastTextView/blob/master/widget.FastTextView/src/main/java/com/lsjwzh/widget/text/FastTextView.java

Sie können auch FastTextView anstelle von Android Textview

Verwandte Themen