使用Spannable的textView - ellipsize不起作用

Pau*_*aul 23 android

我正在尝试修复的问题如下:我正在使用a TextView并且我使用a Spannable设置一些字符粗体.文本需要有2行(android:maxLines="2")的格言,我希望文本被椭圆化,但由于某种原因,我不能使文本椭圆化.

这是简单的代码:

<?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>
Run Code Online (Sandbox Code Playgroud)

和活动:

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

    }
}
Run Code Online (Sandbox Code Playgroud)

文本被截断,不显示"...". 在此输入图像描述

Dal*_*187 16

我意识到这是一个非常古老的帖子,但看到它仍然没有答案,我今天也遇到了这个问题,我想我会发布一个解决方案.希望它能帮助将来的某个人.

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);
        }
    }
});
Run Code Online (Sandbox Code Playgroud)


lan*_*nyf 9

有同样的问题,似乎以下工作对我来说:

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);
Run Code Online (Sandbox Code Playgroud)

在xml中textView已android:multiLine设置,和android:ellipsize="end";和android:singleLine="false;

  • 你暗示我,我使用`textView.setText(spannableStringBuilder,TextView.BufferType.SPANNABLE)`.只需使用`textView.setText(spannableStringBuilder)`就行了. (8认同)
  • 找不到TextView的“ android:mutileLine”。 (2认同)
  • @Sylphe您需要使用TextView.BufferType.SPANNABLE,否则某些文本将被截断。参见/sf/answers/2249777141/ (2认同)

lim*_*lim 6

你是对的,在xml或代码中声明的ellipsize不适用于spannable文本.

但是,通过一些调查,您实际上可以自己做椭圆机:

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

}
Run Code Online (Sandbox Code Playgroud)


小智 5

通过使用反射解决此问题,这可能会有些技巧。阅读AOSP的源代码后,在TextView.java中,DynamicLayout仅包含一个名为sStaticLayout的静态字段成员,并且由新的StaticLayout(null)构造,而没有包括maxLines在内的任何参数。

因此,由于默认情况下将mMaximumVisibleLineCount设置为Integer.MAX_VALUE,所以doEllipsis始终为false。

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我扩展了TextView并创建了一个名为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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

}

问题解决了!

  • @Sheldon Xia:它解决了我一半的问题。如果您有多段文字,则在放置点之后,它还将包含下一段的第一个字母。像这样:嘿,你好... w。你能帮忙吗 (2认同)