前言:在某些应用中,总会遇到一些类似于公告、简介、说明等长文本的TextView,但是为了排版美观等因素,我们通常是要隐藏后半部的文本,而是显示三四行的开始部分(摘要),然后在尾部会提供用户一个扩展/收缩的按钮,使得文本框可以在需要的时候扩展开来查看全文。
前段时间我们的项目也需要这样的效果,就借鉴了一下网上的文章原理并做了算法优化和逻辑修改,自己实现了一个复用性还算可以的可收缩/扩展的TextView:CollapsibleTextView。
今天就贴出来,如果哪位小伙伴需要可以copy一下在项目中使用。
支持功能
1、文本可收起显示特定行数,展开显示全部文本。
2、在文本末尾的 收起/展开 按钮可用文本显示也可用图片icon显示。
3、在文本末尾的 收起/展开 按钮支持在最后一行末尾显示,也支持另起一行在末尾显示。
4、通过修改类代码逻辑可以快速方便定制自己的产品效果。
实现原理
1、收起时使用android:lines来设置TextView的行数,显示特定的行数;点击按钮展开之后,解除行数限制显示全部内容。
2、文本最后的 “...” 省略符号通过在显示文本最后进行手动拼接的形式实现。
3、要记得设置android:layout_height="wrap_content",不然固定了高度,就没法实现了。
4、后缀的按钮是否是文案或者图片通过配置可以控制,生成的方式是最后在onDraw方法给绘制出来。
代码实现
文本展开收起组件的接口:
/**
* 文本展开收起组件的接口
* @author zhangmeng25
*/
public interface ICollapsibleTextViewParent {
void setViewHeight(int height);
}
文案展开收起组件容器:
/**
* 文案展开收起组件
* @author zhangmeng25
*/
public class CollapsibleTextViewParentFrameLayout extends FrameLayout
implements ICollapsibleTextViewParent {
public CollapsibleTextViewParentFrameLayout(@NonNull Context context) {
super(context);
}
public CollapsibleTextViewParentFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public CollapsibleTextViewParentFrameLayout(@NonNull Context context,
@Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void setViewHeight(int height) {
getLayoutParams().height = height + getPaddingTop() + getPaddingBottom();
requestLayout();
}
}
文本展开收起组件:
/**
* 文本展开收起组件
* @author zhangmeng25
*/
public class CollapsibleTextView extends android.support.v7.widget.AppCompatTextView {
/** 动画执行的时间 */
public static final long ANIM_DURATION = 200L;
/** 文本收起后缀 */
public static final String SUFFIX_PREFIX = "...";
/** 文本后缀的文案颜色 */
private int mSuffixColor = 0xff0000ff;
/** 文本收起的行数 */
private int mCollapsedLines = 1;
/** 文本收起的最小行数 */
private int mMinCollapseLines;
/** 当前控件的文本 */
private String mText;
/** 是否需要初始化layout */
private boolean mShouldInitLayout = true;
/** 当前控件是否是展开态 */
private boolean mExpanded = false;
/** 控件的后缀展开文案 */
private String mCollapsedText = " Show All";
/** 控件的后缀收起文案 */
private String mExpandedText = " Hide ";
private String mExpandedChText = " 展开 ";
/** 用于换行的后知文案 */
private String mCollapsedTag = "\n ";
/** 行数变化的动画 */
private ValueAnimator mChangeHeightAnimator;
/** 接口 */
private ICollapsibleTextViewParent mParent;
/** 收起时的高度 */
private int mCollapsedHeight;
/** 后缀文案的尺寸 */
private float mRelativeSize;
/** 后缀文案是否加粗 */
private boolean isSuffixBold;
/** 是否应该显示后缀 */
private boolean showHideSuffix;
/** 是否需要执行动画 */
private boolean doAnimator;
/** 控件的收起显示icon */
private Drawable mTagDrawableClose;
private Bitmap mTagDrawableCloseBitmap;
/** 控件的展开显示icon */
private Drawable mTagDrawableOpen;
private Bitmap mTagDrawableOpenBitmap;
/** 文本展开收起组件点击事件监听 */
private OnCollapsibleClickListener mListener;
public CollapsibleTextView(Context context) {
this(context, null);
}
public CollapsibleTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CollapsibleTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray attributes = context.getTheme()
.obtainStyledAttributes(attrs, R.styleable.CollapsibleTextView, defStyleAttr, 0);
mSuffixColor = attributes.getColor(R.styleable.CollapsibleTextView_suffixColor, 0xff0000ff);
mCollapsedLines = attributes.getInt(R.styleable.CollapsibleTextView_collapsedLines, 2);
mCollapsedText = attributes.getString(R.styleable.CollapsibleTextView_collapsedText);
mMinCollapseLines = attributes.getInteger(R.styleable.CollapsibleTextView_min_collapse_lines, 2);
mRelativeSize = attributes.getFraction(R.styleable.CollapsibleTextView_suffixRelativeSize, 1, 1, 1.f);
isSuffixBold = attributes.getBoolean(R.styleable.CollapsibleTextView_suffixBoldText, false);
showHideSuffix = attributes.getBoolean(R.styleable.CollapsibleTextView_showHideSuffix, true);
doAnimator = attributes.getBoolean(R.styleable.CollapsibleTextView_doAnimator, true);
mTagDrawableClose = attributes.getDrawable(R.styleable.CollapsibleTextView_suffixDrawableClose);
mTagDrawableOpen = attributes.getDrawable(R.styleable.CollapsibleTextView_suffixDrawableOpen);
initTagBitmap(); // 初始化时将标志图片给完成加载构建
if (TextUtils.isEmpty(mCollapsedText)) {
mCollapsedText = " Show All";
}
mExpandedText = attributes.getString(R.styleable.CollapsibleTextView_expandedText);
if (TextUtils.isEmpty(mExpandedText)) {
mExpandedText = " Hide";
}
this.mText = getText() == null ? "" : getText().toString();
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
CollapsibleTextView.this.pendingFullString(!isExpanded(),
Collapsibl