【问题标题】:Ellipsize only a section in a TextView仅椭圆化 TextView 中的一个部分
【发布时间】:2011-03-14 18:53:19
【问题描述】:

我想知道是否可以在 TextView 中仅缩写字符串的一部分。我想做的是这样的:

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

标题应为椭圆形,但 X 必须始终可见。就我而言,不可能使用多个 TextView。您认为有一种简单的方法可以做到这一点吗?

谢谢!

【问题讨论】:

    标签: android string textview abbreviation


    【解决方案1】:

    我真的需要一个干净的项目解决方案,所以在四处寻找并没有找到我喜欢的解决方案后,我花了一些时间来写这篇文章。

    这是一个带有增强省略号控件的 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();
          }
        }
      }
    }
    

    【讨论】:

    • 在我将 layout.getWidth() 更改为 getMeasuredWidth() 之前,我并没有取得太大的成功。根据您的 TextView 所在的布局,这可能会对您有所帮助。
    【解决方案2】:

    你可以试试这样的:

    myTextView.setEllipsize(TextUtils.TruncateAt.MIDDLE);
    

    虽然它可能无法完全满足您的需求,但它可能会执行以下操作:

    带有...标题的元素 (X)

    参考信息

    TruncateAt
    setEllipsize

    【讨论】:

    • 感谢您的回答!这确实不是一个糟糕的解决方案,但并不是我想要的......
    • 除此之外的任何内容,您都必须创建自己的检查并在您想要的位置使用省略号自己绘制。
    猜你喜欢
    • 2013-09-09
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-19
    • 1970-01-01
    相关资源
    最近更新 更多