如图:
?
?1.第一步,新建CollapsibleTextView类继承LinearLayout:
/**
* @author CJF
*/
public class CollapsibleTextView extends LinearLayout {
/**
* (展开与隐藏)文本颜色
*/
private final ForegroundColorSpan expandAndHideColorSpan = new ForegroundColorSpan(Color.parseColor("#3b76ec"));
/**
* (内容文本)文本颜色
*/
private final ForegroundColorSpan textColorSpan = new ForegroundColorSpan(Color.parseColor("#979db0"));
/**
* 文本显示最大行数,默认为1
*/
private int maxLines = 1;
/**
* 标记
*/
private boolean flag, flag2, flag3;
/**
* 文本
*/
private String text;
/**
* 文本长度
*/
private int length;
private TextView mCollapsibleTextView;
public CollapsibleTextView(Context context) {
super(context);
}
public CollapsibleTextView(Context context, AttributeSet attrs) {
super(context, attrs);
View view = inflate(context, R.layout.layout_collapsible_textview, this);
mCollapsibleTextView = (TextView) view.findViewById(R.id.mCollapsibleTextView);
//设置textView可点击
mCollapsibleTextView.setMovementMethod(LinkMovementMethod.getInstance());
}
/**
* 对外提供暴露的方法,为设置文本内容,并设置文本显示最大行数
*
* @param text 设置文本内容
* @param maxLines 设置文本显示最大行数
*/
public void setText(String text, int maxLines) {
this.text = text;
//赋值文本显示最大行数,最小是1
this.maxLines = Math.max(maxLines, 1);
//得到字符串的长度
length = text.length();
//setText调用就设置flag为true
flag = true;
//flag3为false时 设置一次最大行数
if (!flag3) {
//设置默认最大行数
mCollapsibleTextView.setMaxLines(maxLines);
}
//设置文本
mCollapsibleTextView.setText(text);
//重新请求布局
requestLayout();
}
/**
* 文本设置
* 设置展开或隐藏
*
* @param count
* @param str
* @return
*/
private SpannableString getClickableSpan(int count, String str) {
//新建一个spannableString(设置字体颜色,监听点击,字体大小)
SpannableString span = new SpannableString(str);
int maxLines = mCollapsibleTextView.getMaxLines();
if (maxLines == this.maxLines) {
//内容文本 设置字体大小
span.setSpan(new RelativeSizeSpan(1f), 0, count - 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//内容文本 设置字体可点击并监听
span.setSpan(new TextListener(), 0, count - 5, Spanned.SPAN_MARK_MARK);
//内容文本 设置字体颜色
span.setSpan(textColorSpan, 0, count - 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//展开与隐藏 设置字体大小
span.setSpan(new RelativeSizeSpan(1.1f), count - 5, count, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//展开与隐藏 设置字体可点击并监听
span.setSpan(new ExpandAndHideListener(), count - 5, count, Spanned.SPAN_MARK_MARK);
//展开与隐藏 设置字体颜色
span.setSpan(expandAndHideColorSpan, count - 5, count, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
//内容文本 设置字体大小
span.setSpan(new RelativeSizeSpan(1f), 0, count, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//内容文本 设置字体可点击并监听
span.setSpan(new TextListener(), 0, count, Spanned.SPAN_MARK_MARK);
//内容文本 设置字体颜色
span.setSpan(textColorSpan, 0, count, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//展开与隐藏 设置字体大小
span.setSpan(new RelativeSizeSpan(1.1f), count, count + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//展开与隐藏 设置字体可点击并监听
span.setSpan(new ExpandAndHideListener(), count, count + 3, Spanned.SPAN_MARK_MARK);
//展开与隐藏 设置字体颜色
span.setSpan(expandAndHideColorSpan, count, count + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
//返回span
return span;
}
/**
* 1.展开与隐藏的点击事件
* 2.(内容文本的点击事件 与 展开与隐藏文本的点击事件 可全部使用也可只使用一个 这里全部使用)
*/
private class ExpandAndHideListener extends ClickableSpan implements View.OnClickListener {
//文字点击事件
@Override
public void onClick(@NonNull View widget) {
//flag设置并重新请求布局
flagSetting();
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
}
/**
* 内容文本的点击事件
* 2.(内容文本的点击事件 与 展开与隐藏文本的点击事件 可全部使用也可只使用一个 这里全部使用)
*/
private class TextListener extends ClickableSpan implements View.OnClickListener {
//文字点击事件
@Override
public void onClick(@NonNull View widget) {
//flag设置并重新请求布局
flagSetting();
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
}
/**
* flag设置并重新请求布局
*/
private void flagSetting() {
flag = true;
if (flag3) {
//mCollapsibleTextView.getLineCount() <= defaultMaxLines返回true 反之false
flag2 = mCollapsibleTextView.getLineCount() <= maxLines;
//重新请求布局
requestLayout();
}
}
/**
* 布局设置
*
* @param changed
* @param l
* @param t
* @param r
* @param b
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
//flag为false返回
if (!flag) {
return;
}
//设置为false
flag = false;
//flag2为true展开
if (flag2) {
//展开状态
mCollapsibleTextView.setMaxLines(Integer.MAX_VALUE);
//在原字符串后面加上“ 隐藏”
String allText = text + " 隐藏";
SpannableString clickableSpan = getClickableSpan(length, allText);
mCollapsibleTextView.setText(clickableSpan);
flag3 = true;
} else {
//flag2为false 判断mCollapsibleTextView.getLineCount() > defaultMaxLines
if (mCollapsibleTextView.getLineCount() > maxLines) {
//收起状态
mCollapsibleTextView.setMaxLines(maxLines);
//得到第一行最后一个字符的位置
int lineEnd = mCollapsibleTextView.getLayout().getLineEnd(maxLines - 1);
//截取第一行的字符 替换最后五个字符为“...展开”
String hiddenString = text.substring(0, lineEnd - 5) + "...展开";
SpannableString clickableSpan = getClickableSpan(lineEnd, hiddenString);
mCollapsibleTextView.setText(clickableSpan);
flag3 = true;
}
}
}
}
2.第二步,新建布局文件layout_collapsible_textview.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/mCollapsibleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:text="内容"
android:textColor="@color/color_979db0"
android:textSize="14sp" />
</LinearLayout>
3.第三步,在布局中引,com.tq.recorder.widget.customView.CollapsibleTextView是我的包名,替换成你自己的:
<com.tq.recorder.widget.customView.CollapsibleTextView
android:id="@+id/mCollapsibleView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top"
android:textSize="14sp" />
4.第四步,代码中使用,在Activity和适配器中都可以:
CollapsibleTextView view = findViewById(R.id.mCollapsibleView);
//传入文本内容和默认要显示的行数
view.setText("传入文本内容" ,1);
----------------------------------------------------------------end---------------------------------------------------------?
|