我想知道是否可以仅缩写 TextView 中字符串的一部分。我想做的是这样的:
Element with short title (X)
Element with a very lo...(X)
标题应为椭圆形,但 X 必须始终可见。就我而言,不可能使用多个 TextView。你认为有一种简单的方法可以做到这一点吗?
谢谢!
我想知道是否可以仅缩写 TextView 中字符串的一部分。我想做的是这样的:
Element with short title (X)
Element with a very lo...(X)
标题应为椭圆形,但 X 必须始终可见。就我而言,不可能使用多个 TextView。你认为有一种简单的方法可以做到这一点吗?
谢谢!
我真的需要一个干净的项目解决方案,所以在四处寻找并没有找到我喜欢的任何解决方案之后,我花了一些时间来写这个。
这是具有增强的省略号控件的 TextView 的实现。它的工作方式是使用 Android 的 Spanned 界面。它定义了一个枚举,您可以使用它来标记您希望在需要时被省略的特定文本部分。
限制:
以下是使用示例:
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"/>
而已
这是一个结果示例:
实施
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();
}
}
}
}
你可以尝试使用这样的东西:
myTextView.setEllipsize(TextUtils.TruncateAt.MIDDLE);
它可能不会给你你想要的东西,它可能会做这样的事情:
带有...标题的元素 (X)
参考资料