【问题标题】:Set Text View ellipsize and add view more at end设置文本视图椭圆大小并在末尾添加更多视图
【发布时间】:2013-09-30 16:33:43
【问题描述】:

我正在尝试设置文本视图的椭圆大小。使用以下代码。我想在 3 个点后的截断字符串末尾添加“查看更多”。如果使用相同的文本视图可以做到这一点,那就太好了,或者在单独的文本视图中“查看更多”也可以。允许的最大行数为 4。我尝试设置第一个文本视图的宽度,但它在前 3 行末尾留下了空白空间。请看下图。

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >

    <TextView
        android:id="@+id/tvReviewDescription"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:maxLines="4"
        android:text="I tend to shy away from restaurant chains, but wherever I go, PF Chang&apos;s has solidly good food and, like Starbucks, they&apos;re reliable. We were staying in Boston for a week and after a long day and blah blah blah blah... "
        android:textColor="@color/black"
        android:textSize="13dp" 
        android:maxLength="280"
        android:ellipsize="end"/>

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/tvReviewDescription"
        android:layout_alignParentRight="true"
        android:text="@string/label_view_more"
        android:textColor="@color/yellow" />
</RelativeLayout>

【问题讨论】:

  • 你会手动给这个..中的内容吗?比如:“我倾向于回避......”如果是,那么显然你必须控制你的内容被超过,否则你会给出一个列表视图......?
  • @Neha 你能通过代码 sn-p 详细说明吗?他想显示 4 行,如果超过 4 行,则截断文本并显示 'View More' ,给出一些处理多个屏幕的建议。如何手动处理?
  • 点击查看更多会发生什么?此文本是展开还是转到新屏幕?
  • 你找到答案了吗@Basit ZIa

标签: android android-layout


【解决方案1】:

找到我的答案

   public static void makeTextViewResizable(final TextView tv, final int maxLine, final String expandText, final boolean viewMore) {

    if (tv.getTag() == null) {
        tv.setTag(tv.getText());
    }
    ViewTreeObserver vto = tv.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

        @SuppressWarnings("deprecation")
        @Override
        public void onGlobalLayout() {

            ViewTreeObserver obs = tv.getViewTreeObserver();
            obs.removeGlobalOnLayoutListener(this);
            if (maxLine == 0) {
                int lineEndIndex = tv.getLayout().getLineEnd(0);
                String text = tv.getText().subSequence(0, lineEndIndex - expandText.length() + 1) + " " + expandText;
                tv.setText(text);
                tv.setMovementMethod(LinkMovementMethod.getInstance());
                tv.setText(
                        addClickablePartTextViewResizable(Html.fromHtml(tv.getText().toString()), tv, maxLine, expandText,
                                viewMore), TextView.BufferType.SPANNABLE);
            } else if (maxLine > 0 && tv.getLineCount() >= maxLine) {
                int lineEndIndex = tv.getLayout().getLineEnd(maxLine - 1);
                String text = tv.getText().subSequence(0, lineEndIndex - expandText.length() + 1) + " " + expandText;
                tv.setText(text);
                tv.setMovementMethod(LinkMovementMethod.getInstance());
                tv.setText(
                        addClickablePartTextViewResizable(Html.fromHtml(tv.getText().toString()), tv, maxLine, expandText,
                                viewMore), TextView.BufferType.SPANNABLE);
            } else {
                int lineEndIndex = tv.getLayout().getLineEnd(tv.getLayout().getLineCount() - 1);
                String text = tv.getText().subSequence(0, lineEndIndex) + " " + expandText;
                tv.setText(text);
                tv.setMovementMethod(LinkMovementMethod.getInstance());
                tv.setText(
                        addClickablePartTextViewResizable(Html.fromHtml(tv.getText().toString()), tv, lineEndIndex, expandText,
                                viewMore), TextView.BufferType.SPANNABLE);
            }
        }
    });

}

private static SpannableStringBuilder addClickablePartTextViewResizable(final Spanned strSpanned, final TextView tv,
                                                                        final int maxLine, final String spanableText, final boolean viewMore) {
    String str = strSpanned.toString();
    SpannableStringBuilder ssb = new SpannableStringBuilder(strSpanned);

    if (str.contains(spanableText)) {


        ssb.setSpan(new MySpannable(false){
            @Override
            public void onClick(View widget) {
                if (viewMore) {
                    tv.setLayoutParams(tv.getLayoutParams());
                    tv.setText(tv.getTag().toString(), TextView.BufferType.SPANNABLE);
                    tv.invalidate();
                    makeTextViewResizable(tv, -1, "See Less", false);
                } else {
                    tv.setLayoutParams(tv.getLayoutParams());
                    tv.setText(tv.getTag().toString(), TextView.BufferType.SPANNABLE);
                    tv.invalidate();
                    makeTextViewResizable(tv, 3, ".. See More", true);
                }
            }
        }, str.indexOf(spanableText), str.indexOf(spanableText) + spanableText.length(), 0);

    }
    return ssb;

}

另一个类:-

import android.graphics.Color;
import android.text.TextPaint;
import android.text.style.ClickableSpan;
import android.view.View;

public class MySpannable extends ClickableSpan {

private boolean isUnderline = true;

/**
 * Constructor
 */
public MySpannable(boolean isUnderline) {
    this.isUnderline = isUnderline;
}

@Override
public void updateDrawState(TextPaint ds) {
    ds.setUnderlineText(isUnderline);
    ds.setColor(Color.parseColor("#1b76d3"));
}

@Override
public void onClick(View widget) {


 }
}

最后一步调用它:

DetailTv.setText(discription);
makeTextViewResizable(DetailTv, 3, "See More", true);

【讨论】:

  • 回收视图的项目在滚动时刷新。这导致了问题
  • 有人在 Recyclerview 中使用过这个吗?
  • @akansha-rathore 您的代码在 api 24+ 中正常工作,但对于较低版本无法正常工作,我遵循了所有步骤
  • 我不确定,但这个答案不处理链接、表情符号或主题标签。就我而言,我不能插入 URL 或主题标签的中间:www.google.de = www.go see more#germany = #germ see more
【解决方案2】:

比公认的答案简单:

public static final int MAX_LINES = 3;
public static final String TWO_SPACES = " "; 

String myReallyLongText = "Bacon ipsum dolor amet porchetta venison ham fatback alcatra tri-tip, turducken strip steak sausage rump burgdoggen pork loin. Spare ribs filet mignon salami, strip steak ball tip shank frankfurter corned beef venison. Pig pork belly pork chop andouille. Porchetta pork belly ground round, filet mignon bresaola chuck swine shoulder leberkas jerky boudin. Landjaeger pork chop corned beef, tri-tip brisket rump pastrami flank."

textView.setText(myReallyLongText);
textView.post(new Runnable() {
                @Override
                public void run() {
                    // Past the maximum number of lines we want to display.
                    if (textView.getLineCount() > MAX_LINES) {
                        int lastCharShown = textView.getLayout().getLineVisibleEnd(MAX_LINES - 1);

                        textView.setMaxLines(MAX_LINES);

                        String moreString = context.getString(R.string.more);
                        String suffix = TWO_SPACES + moreString;
                        
                        // 3 is a "magic number" but it's just basically the length of the ellipsis we're going to insert
                        String actionDisplayText = myReallyLongText.substring(0, lastCharShown - suffix.length() - 3) + "..." + suffix;

                        SpannableString truncatedSpannableString = new SpannableString(actionDisplayText);
                        int startIndex = actionDisplayText.indexOf(moreString);
                        truncatedSpannableString.setSpan(new ForegroundColorSpan(context.getColor(android.R.color.blue)), startIndex, startIndex + moreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                        textView.setText(truncatedSpannableString);
                    }
                }
            });

如果您希望 Text 的“查看更多”部分是可点击的(但不是整个 TextView),请使用此处所述的 ClickableSpan in this StackOverflow for How to set the part of the text view is clickable。我会提醒你注意这对用户体验的影响,因为通常你会截断你的文本,因为你有很多文本并且你没有太多空间,所以你的字体大小可能已经很小了。让用户单击以导航到全文的小目标可能不是最佳或最容易获得的用户体验,特别是如果您的用户是老年人或有移动问题,难以点击屏幕的一小部分。一般来说,出于这个原因,我建议让您的整个 TextView 可点击,而不是其中的一小部分。

作为替代方案,您可以像我一样将其转换为自定义视图。这是课程;您可以使用 ClickableSpan 代码根据需要进行修改,但由于我已经很久没有编译这个项目了,我不希望进行更改,然后我需要验证是否可以安全发布。如果有人想解决这个问题,我欢迎编辑。

public class TruncatingTextView extends AppCompatTextView {
    private static final String TWO_SPACES = "  ";

    private int truncateAfter = Integer.MAX_VALUE;

    private String suffix;
    private final RelativeSizeSpan truncateTextSpan = new RelativeSizeSpan(0.75f);
    private ForegroundColorSpan viewMoreTextSpan;
    private final String moreString = getContext().getString(R.string.more);

    private final String ellipsis = getContext().getString(R.string.ellipsis);

    public TruncatingTextView(Context context) {
        super(context);
        init();
    }

    public TruncatingTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public TruncatingTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        viewMoreTextSpan = new ForegroundColorSpan(ContextCompat.getColor(getContext(), R.color.upsell_blue));
    }

    public void setText(CharSequence fullText, @Nullable CharSequence afterTruncation, int truncateAfterLineCount) {
        this.suffix = TWO_SPACES + moreString;

        if (!TextUtils.isEmpty(afterTruncation)) {
            suffix += TWO_SPACES + afterTruncation;
        }

        if (this.truncateAfter != truncateAfterLineCount) {
            this.truncateAfter = truncateAfterLineCount;
            setMaxLines(truncateAfter);
        }

        setText(fullText);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        if (getLayout() != null && getLayout().getLineCount() > truncateAfter) {
            int lastCharToShowOfFullTextAfterTruncation = getLayout().getLineVisibleEnd(truncateAfter - 1) - suffix.length() - ellipsis.length();

            int startIndexOfMoreString = lastCharToShowOfFullTextAfterTruncation + TWO_SPACES.length() + 1;

            SpannableString truncatedSpannableString = new SpannableString(getText().subSequence(0, lastCharToShowOfFullTextAfterTruncation) + ellipsis + suffix);
            truncatedSpannableString.setSpan(truncateTextSpan, startIndexOfMoreString, truncatedSpannableString.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
            truncatedSpannableString.setSpan(viewMoreTextSpan, startIndexOfMoreString, startIndexOfMoreString + moreString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            setText(truncatedSpannableString);
        }
    }
}

【讨论】:

  • 这里的“TWO_SPACES”是什么?
  • 字面上是两个空格的常数。公共静态最终字符串 TWO_SPACES = " ";
  • 根据我的实施经验——这个答案对我帮助很大,IMO 是一个很好的直接解决方案。
  • 如何让视图更可点击?
  • 更简单,因为你没有点击句柄
【解决方案3】:

这可以在运行时实现,你需要做的就是检查字符串的长度,并在字符串的末尾添加下划线查看更多。

我以长度'20'为例,你可以根据你的要求改变。

final TextView result = (TextView) findViewById(R.id.textview);

String text = "I tend to shy away from restaurant chains, but wherever I go, PF Chang&apos;s has solidly good food and, like Starbucks, they&apos;re reliable. We were staying in Boston for a week and after a long day and blah blah blah blah...";

if (text.length()>20) {
    text=text.substring(0,20)+"...";
    result.setText(Html.fromHtml(text+"<font color='red'> <u>View More</u></font>"));       

}

【讨论】:

  • 如果您更改设备方向,可能会显示全文,因此不再需要“查看更多”。我认为您的解决方案既不是“字体大小”也不是独立于屏幕分辨率的。
  • 感谢分享代码 sn-p。我需要知道如何执行查看更多文本的点击事件?
  • 虽然我认为这不是一个好的解决方案,因为它取决于特定的屏幕尺寸等,设置事件监听很容易,因为这是一个TextView,只需让用户大手指点击TextView 上的任何位置。
  • 感谢您的回答。改进它我已在查看更多和显示更少文本上发布了点击事件侦听器的答案
【解决方案4】:

查看我的图书馆:https://github.com/AhmMhd/SeeMoreTextView-Android

<com.abdulhakeem.seemoretextview.SeeMoreTextView
    android:id="@+id/textview
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
/>

用法:

TextView seemoreTv = (TextView) findViewById(R.id.textview)

seemoreTv.setContent("some really long text here.")

它在 recyclerview 上也很有效。

【讨论】:

  • 嗨,阿卜杜勒,谢谢。你拯救了我的一天 :-) 祝你好运!
【解决方案5】:

这会有椭圆的效果。

设置布尔 isCheck=true;

把它放在xml中:

<TextView
        android:id="@+id/txt_id"
        android:maxLines="2"
        android:ellipsize="end"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

和代码:

txt_id= (TextView)findViewById(R.id.txt_id);
txt_id.setText("data");
txt_id.setOnClickListener(new View.OnClickListener() {
     @Override
     public void onClick(View view) {
                   if (isCheck) {
                      txt_id.setMaxLines(10);
                      isCheck = false;
                   } else {
                      txt_id.setMaxLines(2);
                      isCheck = true;
           }
       }
  }

【讨论】:

    【解决方案6】:

    在 Kotlin 适配器中,您可以这样写到 TextView 上的“查看更多”

    if (News[position].description.length > 150) {
      holder.desc.text = Html.fromHtml(News[position].description.substring(0, 150) + "..." + "<font color='blue'> <u>View More</u></font>")
    } else {
       holder.desc.text = News[position].description
    }
    holder.desc.setOnClickListener {
       if (holder.desc.text.toString().endsWith("View More")) {
          holder.desc.text = News[position].description
       } else {
          if (News[position].description.length > 150) {
            holder.desc.text = Html.fromHtml(News[position].description.substring(0, 150) + "..." + "<font color='blue'> <u>View More</u></font>")
          } else holder.desc.text = News[position].description
       }
    }
    

    【讨论】:

    • 很好的答案。谢谢
    【解决方案7】:

    这个解决方案更容易在代码中实现。它不能很好地支持动态更改,但可以很容易地进行修改。

    public class ExpandableTextView extends TextView {
    
        private final String readMoreText = "...read more";
        private final int readMoreColor = Color.parseColor("#4A0281");
    
        private int _maxLines = 4;
        private CharSequence originalText;
    
        public ExpandableTextView(Context context) {
            super(context);
            init(context);
        }
    
        public ExpandableTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context);
        }
    
        public ExpandableTextView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init(context);
        }
    
        private void init(Context context) {
    
            ViewTreeObserver vto = getViewTreeObserver();
            vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    
                @SuppressWarnings("deprecation")
                @Override
                public void onGlobalLayout() {
    
                    ViewTreeObserver obs = getViewTreeObserver();
                    obs.removeGlobalOnLayoutListener(this);
    
                    truncateText();
                }
            });
        }
    
        @Override
        public void setText(CharSequence text, BufferType type) {
            super.setText(text, type);
    
            if (originalText == null) {
                originalText = text;
            }
        }
    
        @Override
        public int getMaxLines() {
            return _maxLines;
        }
    
        @Override
        public void setMaxLines(int maxLines) {
            _maxLines = maxLines;
        }
    
        public void truncateText() {
    
            int maxLines = _maxLines;
            String text = getText().toString();
    
            if (getLineCount() >= maxLines) {
    
                int lineEndIndex = getLayout().getLineEnd(maxLines - 1);
    
                String truncatedText = getText().subSequence(0, lineEndIndex - readMoreText.length() + 1) + readMoreText;
    
                Spannable spannable = new SpannableString(truncatedText);
                spannable.setSpan(new ForegroundColorSpan(readMoreColor), truncatedText.length() - readMoreText.length(), truncatedText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    
                setText(spannable, TextView.BufferType.SPANNABLE);
    
                super.setMaxLines(_maxLines);
            }
        }
    
        public void expandText() {
            setText(originalText);
            super.setMaxLines(1000);
        }
    
        public void reset() {
            originalText = null;
        }
    }
    

    【讨论】:

    • tnanks ,但我无法点击阅读更多文本来扩展文本
    【解决方案8】:

    在上述解决方案中,扩展文本(查看更多/更少) 显示,如果文本的长度小于最大行数。在这个类中,我删除了这个错误。您只需要将此类放入您的代码中并在 XML 中使用它。您可以根据自己的要求轻松修改(扩展文本的颜色、字体样式等)

          public class ExpandableTextView extends AppCompatTextView {
    
        private static Context context;
        private TextView textView;
        private int maxLine = 3;
        private boolean isViewMore = true;
    
        public ExpandableTextView(Context context) {
            super(context);
            ExpandableTextView.context = context;
            textView = this;
            initViews();
        }
    
        public ExpandableTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
            ExpandableTextView.context = context;
            textView = this;
            initViews();
        }
    
        public ExpandableTextView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            ExpandableTextView.context = context;
            textView = this;
            initViews();
        }
    
        public void initViews() {
            if (textView.getText().toString().isEmpty()) {
                return;
            }
            if (textView.getTag() == null) {
                textView.setTag(textView.getText());
            }
            textView.setTypeface(Typeface.createFromAsset(context.getAssets(), "GothamBook.ttf"));
            ViewTreeObserver vto = textView.getViewTreeObserver();
            vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @SuppressWarnings("deprecation")
                @Override
                public void onGlobalLayout() {
                    String text, expandText = "See ";
                    int lineEndIndex;
                    ViewTreeObserver obs = textView.getViewTreeObserver();
                    obs.removeGlobalOnLayoutListener(this);
                    int lineCount = textView.getLayout().getLineCount();
    
                    expandText += isViewMore ? "More" : "Less";
                    if (lineCount <= maxLine) {
                        lineEndIndex = textView.getLayout().getLineEnd(textView.getLayout().getLineCount() - 1);
                        text = textView.getText().subSequence(0, lineEndIndex).toString();
                    } else if (isViewMore && maxLine > 0 && textView.getLineCount() >= maxLine) {
                        lineEndIndex = textView.getLayout().getLineEnd(maxLine - 1);
                        text = textView.getText().subSequence(0, lineEndIndex - expandText.length() + 1) + " " + expandText;
                    } else {
                        lineEndIndex = textView.getLayout().getLineEnd(textView.getLayout().getLineCount() - 1);
                        text = textView.getText().subSequence(0, lineEndIndex) + " " + expandText;
                    }
                    textView.setText(text);
                    textView.setMovementMethod(LinkMovementMethod.getInstance());
                    if (lineCount > maxLine)
                        textView.setText(addClickablePartTextViewResizable(expandText),
                                BufferType.SPANNABLE);
                    textView.setSelected(true);
                }
            });
        }
    
        private SpannableStringBuilder addClickablePartTextViewResizable(final String expandText) {
            String string = textView.getText().toString();
            SpannableStringBuilder expandedStringBuilder = new SpannableStringBuilder(string);
            if (string.contains(expandText)) {
                expandedStringBuilder.setSpan(new ClickableSpan() {
                    @Override
                    public void onClick(View widget) {
                        textView.setLayoutParams(textView.getLayoutParams());
                        textView.setText(textView.getTag().toString(), BufferType.SPANNABLE);
                        textView.invalidate();
                        maxLine = isViewMore ? -1 : 3;
                        isViewMore = !isViewMore;
                        initViews();
                    }
    
                    @Override
                    public void updateDrawState(@NonNull TextPaint ds) {
                        ds.setUnderlineText(true);
                        ds.setColor(context.getResources().getColor(R.color.red));
                        ds.setTypeface(Typeface.createFromAsset(context.getAssets(), "GothamMedium.ttf"));
                    }
                }, string.indexOf(expandText), string.length(), 0);
            }
            return expandedStringBuilder;
        }
    }
    

    如果你设置动态数据,你需要在将文本设置到文本视图后调用 initViews()。

    tvDescription.setText(sessionModel.getDescription());
    tvDescription.initViews();
    

    【讨论】:

    • 在回收站视图中使用了它,它运行良好。谢谢兄弟
    • 在回收站视图中它只在第一次工作。但后来当向下滚动并第二次向上滚动时,它就不起作用了..
    • @AdityaPatil 如您所见,此类中使用的所有变量都是本地变量。因此,当您滚动回收器视图时,它们会重置,因为它会重新创建所有视图。您必须从列表数据中管理 isViewMore 变量。
    【解决方案9】:

    感谢 Jitender 的回答。改进它我已经根据文本长度完成了以下实现。如果您想要在指定的行数之后查看更多选项但假设大约有 50 个字符,这可能不是理想的解决方案如果您可以调整行数,则单行该解决方案将运行良好。如果文本长度大于 150,以下解决方案将添加“查看更多”选项,并将文本省略为 150 个字符。单击“查看更多”它将显示完整的文本Show Less 选项并再次单击 Show Less 会将文本省略为 150 个字符。不需要单独的视图。它也适用于 recyclerview 项目的 textview。

    if(inputText.length()>150)
            {
                String text=inputText.substring(0,150)+"...";
                final String fulltext=inputText;
    
                final SpannableString ss = new SpannableString(text+"View More");
    
                ClickableSpan span1 = new ClickableSpan() {
                    @Override
                    public void onClick(View textView) {
                        // do some thing
                        SpannableString ss1 = new SpannableString(fulltext+"Show Less");
                        ClickableSpan span2 = new ClickableSpan() {
                            @Override
                            public void onClick(View textView) {
                                // do some thing
                                textView.setText(ss);
                                textView.setMovementMethod(LinkMovementMethod.getInstance());
    
                            }
                        };
                        ss1.setSpan(span2, fulltext.length(), ss1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                        ss1.setSpan(new ForegroundColorSpan(Color.BLUE), fulltext.length(), ss1.length(),
                                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    
    
                        textView.setText(ss1);
                        textView.setMovementMethod(LinkMovementMethod.getInstance());
                    }
                };
                ss.setSpan(span1, 153, 162, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                ss.setSpan(new ForegroundColorSpan(Color.BLUE), 153,162,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    
                textView.setText(ss);
                textView.setMovementMethod(LinkMovementMethod.getInstance());
            }
    else
            {
                textView.setText(inputText);
            }
    

    【讨论】:

      【解决方案10】:

      您可以使用以下代码;

       holder.tvMoreInfo.setText(horizontalList.get(position));
      
              holder.tvMoreInfo.post(new Runnable() {
                  @Override
                  public void run() {
                      int lineCount = holder.tvMoreInfo.getLineCount();
                      if (lineCount<3)
                      {
      
                      }else
                      {
                          makeTextViewResizable(holder.tvMoreInfo, 3, "...More", true);
                      }
                  }
              });
      
      
      
       public static void makeTextViewResizable(final TextView tv, final int maxLine, final String expandText, final boolean viewMore) {
      
          if (tv.getTag() == null) {
              tv.setTag(tv.getText());
          }
          ViewTreeObserver vto = tv.getViewTreeObserver();
          vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
      
              @SuppressWarnings("deprecation")
              @Override
              public void onGlobalLayout() {
                  String text;
                  int lineEndIndex;
                  ViewTreeObserver obs = tv.getViewTreeObserver();
                  obs.removeGlobalOnLayoutListener(this);
                  if (maxLine == 0) {
                      lineEndIndex = tv.getLayout().getLineEnd(0);
                      text = tv.getText().subSequence(0, lineEndIndex - expandText.length() + 1) + " " + "<font color=\"#F15d36\">" + expandText + "</font>";
                  } else if (maxLine > 0 && tv.getLineCount() >= maxLine) {
                      lineEndIndex = tv.getLayout().getLineEnd(maxLine - 1);
                      text = tv.getText().subSequence(0, lineEndIndex - expandText.length() + 1) + " " + "<font color=\"#F15d36\">" + expandText + "</font>";
                  } else {
                      lineEndIndex = tv.getLayout().getLineEnd(tv.getLayout().getLineCount() - 1);
                      text = tv.getText().subSequence(0, lineEndIndex) + " " + "<font color=\"#F15d36\">" + expandText + "</font>";
                  }
                  tv.setText(Html.fromHtml(text));
                  tv.setMovementMethod(LinkMovementMethod.getInstance());
      
                  tv.setText(
                          addClickablePartTextViewResizable(Html.fromHtml(tv.getText().toString()), tv, lineEndIndex, expandText,
                                  viewMore), TextView.BufferType.SPANNABLE);
              }
          });
      }
      
      private static SpannableStringBuilder addClickablePartTextViewResizable(final Spanned strSpanned, final TextView tv,
                                                                              final int maxLine, final String spanableText, final boolean viewMore) {
          String str = strSpanned.toString();
          SpannableStringBuilder ssb = new SpannableStringBuilder(strSpanned);
      
          if (str.contains(spanableText)) {
              ssb.setSpan(new MySpannable(false) {
      
                  @Override
                  public void onClick(View widget) {
                      tv.setLayoutParams(tv.getLayoutParams());
                      tv.setText(tv.getTag().toString(), TextView.BufferType.SPANNABLE);
                      tv.invalidate();
                      if (viewMore) {
                          makeTextViewResizable(tv, -1, "...Less", false);
                      } else {
                          makeTextViewResizable(tv, 3, "...More", true);
                      }
      
                  }
              }, str.indexOf(spanableText), str.indexOf(spanableText) + spanableText.length(), 0);
      
          }
          return ssb;
      
      }
      

      【讨论】:

      • 感谢正常情况下的作品。对 recyclerview 没有帮助。
      【解决方案11】:

      可能会晚,但它是在 recyclerview 中处理此问题的最简单且经过测试的方法。

      首先检查textview的长度,如果需要,可以设置更多的视图

      
      if (inventory.getDescription().length()>90) {
        inventoryDescription.setText(Html.fromHtml(inventory.getDescription().substring(0,90)+"..."+"<font color='blue'> <u>View More</u></font>"));
       }
       else inventoryDescription.setText(inventory.getDescription());
      
      

      在 textview 中点击监听器

      inventoryDescription.setOnClickListener(new View.OnClickListener() {
                  @Override
          public void onClick(View v) {
      
         if (inventoryDescription.getText().toString().endsWith("View More")) {
             inventoryDescription.setText(inventory.getDescription());
            } 
          else {
      
         if (inventory.getDescription().length()>90) {
       inventoryDescription.setText(Html.fromHtml(inventory.getDescription().substring(0,90)+"..."+"<font color='blue'> <u>View More</u></font>"));
      
         }
         else inventoryDescription.setText(inventory.getDescription());
          }
      
                  }
              });
      
      

      【讨论】:

        【解决方案12】:

        尝试使用这个库:)

        //将此依赖添加到App Gradle中

        implementation 'com.borjabravo:readmoretextview:2.1.0'
        

        用法:

        <com.borjabravo.readmoretextview.ReadMoreTextView
           android:id="@+id/text2"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:layout_marginTop="@dimen/activity_vertical_margin"
           android:text="@string/DemoText"
           app:colorClickableText="#3F51B5"/>
        

        查看此链接:https://github.com/bravoborja/ReadMoreTextView

        【讨论】:

        • 是否有一个选项可以让我将点击侦听器设置为仅“Readmore”文本
        【解决方案13】:

        我写了一篇关于我如何在我们的应用程序中做到这一点的博客文章。它基于这里的一些其他解决方案,它可以显示read more.../read less,并且在RecyclerViews中也很有效,因为文本是在主线程上立即计算出来的。

        Here's the blog post.

        And here's the code, which is also linked in the post.

        【讨论】:

          【解决方案14】:

          而不是使用 android:layout_alignParentLeft="true" 在第一次使用 textview android:layout_toLeftOf="@+id/textView1"

          这应该处理重叠的文本

          【讨论】:

          • 这永远无法满足要求。
          • 请解释为什么不这样做?
          • 这将在以上3行视图中多留空白。
          猜你喜欢
          • 1970-01-01
          • 2011-04-30
          • 2014-01-30
          • 2014-01-06
          • 2011-04-30
          • 2021-08-06
          • 2016-02-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多