[真实有效]自定义可展开收起TextView,展开收起按钮紧跟文本内容

xiaoxiao2021-03-01  53

ExpandTextView.class import android.annotation.SuppressLint; import android.content.Context; import android.os.Build; import android.text.Layout; import android.text.SpannableString; import android.text.Spanned; import android.text.StaticLayout; import android.text.method.LinkMovementMethod; import android.util.AttributeSet; import android.view.View; import android.widget.TextView; import com.yimiao100.sale.yimiaomanager.R; @SuppressLint("AppCompatCustomView") public class ExpandTextView extends TextView { private String originText;// 原始内容文本 private int initWidth = 0;// TextView可展示宽度 private int mMaxLines = 3;// TextView最大行数 private SpannableString SPAN_CLOSE = null;// 收起的文案(颜色处理) private SpannableString SPAN_EXPAND = null;// 展开的文案(颜色处理) private String TEXT_EXPAND = " 展开描述问题>"; private String TEXT_CLOSE = " <收起"; public ExpandTextView(Context context) { super(context); initCloseEnd(); } public ExpandTextView(Context context, AttributeSet attrs) { super(context, attrs); initCloseEnd(); } public ExpandTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initCloseEnd(); } /** * 设置TextView可显示的最大行数 * @param maxLines 最大行数 */ @Override public void setMaxLines(int maxLines) { this.mMaxLines = maxLines; super.setMaxLines(maxLines); } /** * 初始化TextView的可展示宽度 * @param width */ public void initWidth(int width){ initWidth = width; } /** * 收起的文案(颜色处理)初始化 */ private void initCloseEnd(){ String content = TEXT_EXPAND; SPAN_CLOSE = new SpannableString(content); ButtonSpan span = new ButtonSpan(getContext(), new View.OnClickListener(){ @Override public void onClick(View v) { ExpandTextView.super.setMaxLines(Integer.MAX_VALUE); setExpandText(originText); } }, R.color.colorAccent); SPAN_CLOSE.setSpan(span, 0, content.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); } /** * 展开的文案(颜色处理)初始化 */ private void initExpandEnd(){ String content = TEXT_CLOSE; SPAN_EXPAND = new SpannableString(content); ButtonSpan span = new ButtonSpan(getContext(), new View.OnClickListener(){ @Override public void onClick(View v) { ExpandTextView.super.setMaxLines(mMaxLines); setCloseText(originText); } }, R.color.colorAccent); SPAN_EXPAND.setSpan(span, 0, content.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE); } public void setCloseText(CharSequence text) { if(SPAN_CLOSE == null){ initCloseEnd(); } boolean appendShowAll = false;// true 不需要展开收起功能, false 需要展开收起功能 originText = text.toString(); // SDK >= 16 可以直接从xml属性获取最大行数 int maxLines = 0; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) { maxLines = getMaxLines(); } else{ maxLines = mMaxLines; } String workingText = new StringBuilder(originText).toString(); if (maxLines != -1) { Layout layout = createWorkingLayout(workingText); if (layout.getLineCount() > maxLines) { //获取一行显示字符个数,然后截取字符串数 workingText = originText.substring(0, layout.getLineEnd(maxLines - 1)).trim();// 收起状态原始文本截取展示的部分 String showText = originText.substring(0, layout.getLineEnd(maxLines - 1)).trim() + "..." + SPAN_CLOSE; Layout layout2 = createWorkingLayout(showText); // 对workingText进行-1截取,直到展示行数==最大行数,并且添加 SPAN_CLOSE 后刚好占满最后一行 while (layout2.getLineCount() > maxLines) { int lastSpace = workingText.length()-1; if (lastSpace == -1) { break; } workingText = workingText.substring(0, lastSpace); layout2 = createWorkingLayout(workingText + "..." + SPAN_CLOSE); } appendShowAll = true; workingText = workingText + "..."; } } setText(workingText); if (appendShowAll) { // 必须使用append,不能在上面使用+连接,否则spannable会无效 append(SPAN_CLOSE); setMovementMethod(LinkMovementMethod.getInstance()); } } public void setExpandText(String text) { if(SPAN_EXPAND == null){ initExpandEnd(); } Layout layout1 = createWorkingLayout(text); Layout layout2 = createWorkingLayout(text + TEXT_CLOSE); // 展示全部原始内容时 如果 TEXT_CLOSE 需要换行才能显示完整,则直接将TEXT_CLOSE展示在下一行 if(layout2.getLineCount() > layout1.getLineCount()){ setText(originText + "\n"); }else{ setText(originText); } append(SPAN_EXPAND); setMovementMethod(LinkMovementMethod.getInstance()); } //返回textview的显示区域的layout,该textview的layout并不会显示出来,只是用其宽度来比较要显示的文字是否过长 private Layout createWorkingLayout(String workingText) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { return new StaticLayout(workingText, getPaint(), initWidth - getPaddingLeft() - getPaddingRight(), Layout.Alignment.ALIGN_NORMAL, getLineSpacingMultiplier(), getLineSpacingExtra(), false); } else{ return new StaticLayout(workingText, getPaint(), initWidth - getPaddingLeft() - getPaddingRight(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false); } } }

 

ButtonSpan.class

import android.content.Context; import android.text.TextPaint; import android.text.style.ClickableSpan; import android.view.View; import com.yimiao100.sale.yimiaomanager.R; /** * Created by Michel on 2018/7/24. */ public class ButtonSpan extends ClickableSpan { View.OnClickListener onClickListener; private Context context; private int colorId; public ButtonSpan(Context context, View.OnClickListener onClickListener) { this(context, onClickListener, R.color.colorAccent); } public ButtonSpan(Context context, View.OnClickListener onClickListener, int colorId){ this.onClickListener = onClickListener; this.context = context; this.colorId = colorId; } public void updateDrawState(TextPaint ds) { ds.setColor(context.getResources().getColor(colorId)); ds.setUnderlineText(false); } public void onClick(View widget) { if (onClickListener != null) { onClickListener.onClick(widget); } } } ScreenUtils class import android.content.Context; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.WindowManager; /** * Created by chenjie on 18-7-26. */ public class ScreenUtils { private ScreenUtils() { /* cannot be instantiated */ throw new UnsupportedOperationException("cannot be instantiated"); } /** * 获得屏幕宽度 * * @param context * @return */ public static int getScreenWidth(Context context) { WindowManager wm = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(outMetrics); return outMetrics.widthPixels; } /** * dp转px * * @param context * @param dpVal * @return */ public static int dp2px(Context context, float dpVal) { return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, context.getResources().getDisplayMetrics()); } }

 

使用

  list = new ArrayList<String>(); for (int i = 1; i < 10; i++) { list.add("aaaaaaqqqqqqqqqqqqqqqqqqqqqqqqqqqaaaaeeeeeeeeeeeeeeeeeeeeeeeeeaaaa" + "aaaaaaaqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqaaaaaa," + "aaaaaqqqqqqqqqqqqqqqqqqqqaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + "aaaaaaaaaaaaaaaaaaaaaaaaa"); } int whidth = ScreenUtils.getScreenWidth(getActivity()) - ScreenUtils.dp2px(getActivity(),16*2); holder.text_expand.initWidth(whidth); holder.text_expand.setMaxLines(3); holder.text_expand.setCloseText(list.get(position));
转载请注明原文地址: https://www.6miu.com/read-4199933.html

最新回复(0)