我正在尝试设置文本视图的椭圆化。使用以下代码。我想在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's has solidly good food and, like Starbucks, they'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>
答案 0 :(得分:15)
这可以在运行时实现,您需要做的就是检查字符串的长度,并在字符串的末尾添加带下划线的View More。
我使用长度'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's has solidly good food and, like Starbucks, they'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>"));
}
答案 1 :(得分:13)
找到我的答案
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);
答案 2 :(得分:7)
比接受的答案简单:
public static final int MAX_LINES = 3;
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);
}
}
});
答案 3 :(得分:4)
这将产生椭圆效应。
set Boolean 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;
}
}
}
答案 4 :(得分:1)
感谢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);
}
答案 5 :(得分:1)
签出我的图书馆: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上也很好用。
答案 6 :(得分:1)
在上述解决方案中,扩展文本(请参阅更多/更少) 显示,如果文本的长度小于最大行数。在此类中,我删除了此错误。您只需要将该类放入代码中并在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();
答案 7 :(得分:1)
在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
}
}
答案 8 :(得分:0)
此解决方案在代码中更容易实现。它不能很好地支持即时更改,但可以轻松修改以实现此目的。
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;
}
}
答案 9 :(得分:0)
您可以为此使用以下代码;
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;
}
答案 10 :(得分:0)
可能已经晚了,但是它是在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());
}
}
});
答案 11 :(得分:0)
尝试使用此库:)
///将此依赖项添加到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"/>
答案 12 :(得分:0)
我写了一篇关于我如何在我们的应用程序中做到这一点的博客文章。它基于这里的一些其他解决方案,它可以显示read more...
/ read less
,并且在 RecyclerViews 中也很有效,因为文本是立即在主线程上计算的。
答案 13 :(得分:-2)
而不是使用 android:layout_alignParentLeft =“true”在第一个textview使用中 机器人:layout_toLeftOf = “@ + ID / textView1”
这应该处理重叠文本