1、可折叠的TextView,做学习保留,引用:
https://github.com/hymanme/ExpandTextView
public class ExpandTextView extends LinearLayout implements View.OnClickListener {
public static final String TAG = "ExpandTextView";
public static final int DEFAULT_TITLE_TEXT_COLOR = 0X8A000000;
public static final int DEFAULT_CONTENT_TEXT_COLOR = 0XDE000000;
public static final int DEFAULT_HINT_TEXT_COLOR = 0XDE000000;
public static final int DEFAULT_MIN_LINES = 4;
public static final int DEFAULT_TITLE_TEXT_SIZE = 16;
public static final int DEFAULT_CONTENT_TEXT_SIZE = 14;
public static final int DEFAULT_HINT_TEXT_SIZE = 12;
public static final int DEFAULT_ANIMATION_DURATION = 600;
private Context mContext;
//标题
private String title;
//内容文字
private String content;
//展开后显示的文字
private String foldHint;
//折叠起来后显示的文字
private String expandHint;
//标题文字颜色
private int titleTextColor;
//内容文字颜色
private int contentTextColor;
//查看更多文字颜色
private int hintTextColor;
//查看更多前面显示的小图标
private Drawable indicateImage;
//内容区域最少显示几行文字
private int minVisibleLines;
//标题字体大小
private float titleTextSize;
//内容字体大小
private float contentTextSize;
//提示字体大小
private float hintTextSize;
//展开和折叠动画持续时间
private int animationDuration;
private TextView mTitleView;
private TextView mContentView;
private TextView mHintView;
private ImageView mIndicateImage;
private RelativeLayout mShowMore;
private TextView copy;
private OnReadMoreClickListener mListener;
// 是否已经展开
private boolean flag;
public ExpandTextView(Context context) {
this(context, null);
}
public ExpandTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ExpandTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
setOrientation(VERTICAL);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ExpandTextView);
title = a.getString(R.styleable.ExpandTextView_titleText);
content = a.getString(R.styleable.ExpandTextView_contentText);
foldHint = a.getString(R.styleable.ExpandTextView_foldHint);
expandHint = a.getString(R.styleable.ExpandTextView_expandHint);
titleTextColor = a.getColor(R.styleable.ExpandTextView_textTitleColor, DEFAULT_TITLE_TEXT_COLOR);
contentTextColor = a.getColor(R.styleable.ExpandTextView_textContentColor, DEFAULT_CONTENT_TEXT_COLOR);
hintTextColor = a.getColor(R.styleable.ExpandTextView_textHintColor, DEFAULT_HINT_TEXT_COLOR);
indicateImage = a.getDrawable(R.styleable.ExpandTextView_indicateImage);
minVisibleLines = a.getInt(R.styleable.ExpandTextView_minVisibleLines, DEFAULT_MIN_LINES);
titleTextSize = a.getDimension(R.styleable.ExpandTextView_titleTextSize, sp2px(mContext, DEFAULT_TITLE_TEXT_SIZE));
contentTextSize = a.getDimension(R.styleable.ExpandTextView_contentTextSize, sp2px(mContext, DEFAULT_CONTENT_TEXT_SIZE));
hintTextSize = a.getDimension(R.styleable.ExpandTextView_hintTextSize, sp2px(mContext, DEFAULT_HINT_TEXT_SIZE));
animationDuration = a.getInt(R.styleable.ExpandTextView_animationDuration, DEFAULT_ANIMATION_DURATION);
a.recycle();
init();
}
/**
* 初始化
*/
private void init() {
View.inflate(mContext, R.layout.expand_text_view, this);
mTitleView = (TextView) findViewById(R.id.tv_title);
mContentView = (TextView) findViewById(R.id.tv_content);
mHintView = (TextView) findViewById(R.id.tv_more_hint);
mIndicateImage = (ImageView) findViewById(R.id.iv_arrow_more);
mShowMore = (RelativeLayout) findViewById(R.id.rl_show_more);
mTitleView.setText(title);
mTitleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleTextSize);
mTitleView.setTextColor(titleTextColor);
mContentView.setText(content);
mContentView.setTextSize(TypedValue.COMPLEX_UNIT_PX, contentTextSize);
mContentView.setTextColor(contentTextColor);
mHintView.setText(expandHint);
mHintView.setTextSize(TypedValue.COMPLEX_UNIT_PX, hintTextSize);
mHintView.setTextColor(hintTextColor);
if (indicateImage == null) {
indicateImage = getResources().getDrawable(R.drawable.ic_arrow_down_light_round);
}
mIndicateImage.setImageDrawable(indicateImage);
mShowMore.setOnClickListener(this);
ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
layoutParams.height = getMinMeasureHeight();
mContentView.setLayoutParams(layoutParams);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
mTitleView.setText(title);
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
mContentView.setText(content);
}
public String getFoldHint() {
return foldHint;
}
public void setFoldHint(String foldHint) {
this.foldHint = foldHint;
}
public String getExpandHint() {
return expandHint;
}
public void setExpandHint(String expandHint) {
this.expandHint = expandHint;
}
public int getTitleTextColor() {
return titleTextColor;
}
public void setTitleTextColor(@ColorInt int titleTextColor) {
this.titleTextColor = titleTextColor;
mTitleView.setTextColor(titleTextColor);
}
public int getContentTextColor() {
return contentTextColor;
}
public void setContentTextColor(@ColorInt int contentTextColor) {
this.contentTextColor = contentTextColor;
mContentView.setTextColor(contentTextColor);
}
public int getHintTextColor() {
return hintTextColor;
}
public void setHintTextColor(@ColorInt int hintTextColor) {
this.hintTextColor = hintTextColor;
mHintView.setTextColor(hintTextColor);
}
public Drawable getIndicateImage() {
return indicateImage;
}
public void setIndicateImage(@DrawableRes Drawable indicateImage) {
this.indicateImage = indicateImage;
mIndicateImage.setImageDrawable(indicateImage);
}
public void setIndicateImage(@DrawableRes int indicateImageRes) {
this.indicateImage = getResources().getDrawable(indicateImageRes);
mIndicateImage.setImageDrawable(this.indicateImage);
}
public int getMinVisibleLines() {
return minVisibleLines;
}
public void setMinVisibleLines(int minVisibleLines) {
this.minVisibleLines = minVisibleLines;
copy = null;
ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
layoutParams.height = getMinMeasureHeight();
mContentView.setLayoutParams(layoutParams);
}
public float getTitleTextSize() {
return titleTextSize;
}
/**
* 设置字体大小
*
* @param titleTextSize sp为单位
*/
public void setTitleTextSize(float titleTextSize) {
this.titleTextSize = sp2px(mContext, titleTextSize);
mTitleView.setTextSize(titleTextSize);
}
public float getContentTextSize() {
return contentTextSize;
}
/**
* 设置字体大小
*
* @param contentTextSize sp为单位
*/
public void setContentTextSize(float contentTextSize) {
this.contentTextSize = sp2px(mContext, contentTextSize);
mContentView.setTextSize(contentTextSize);
copy = null;
ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
layoutParams.height = getMinMeasureHeight();
mContentView.setLayoutParams(layoutParams);
}
public float getHintTextSize() {
return hintTextSize;
}
/**
* 设置字体大小
*
* @param hintTextSize sp为单位
*/
public void setHintTextSize(float hintTextSize) {
this.hintTextSize = sp2px(mContext, hintTextSize);
mHintView.setTextSize(hintTextSize);
}
public View getTitleView() {
return mTitleView;
}
public int getAnimationDuration() {
return animationDuration;
}
public void setAnimationDuration(int animationDuration) {
this.animationDuration = animationDuration;
}
public OnReadMoreClickListener getReadMoreListener() {
return mListener;
}
public void setOnReadMoreListener(OnReadMoreClickListener mListener) {
this.mListener = mListener;
}
@Override
public void onClick(View view) {
if (view.getId() == R.id.rl_show_more) {
expand();
}
}
/**
* 获取TextView最大高度
*
* @return int 最大测量高度
*/
public int getMaxMeasureHeight() {
int width = mContentView.getMeasuredWidth();
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(3000, View.MeasureSpec.AT_MOST);
mContentView.measure(widthMeasureSpec, heightMeasureSpec);
return mContentView.getMeasuredHeight();
}
/**
* 获取TextView最小高度
*
* @return int 最小测量高度
*/
public int getMinMeasureHeight() {
if (copy == null) {
copy = new TextView(mContext);
copy.setTextSize(TypedValue.COMPLEX_UNIT_PX, contentTextSize);
copy.setLineSpacing(dp2px(mContext, 6), 1.0f);
copy.setLines(minVisibleLines);
}
int width = mContentView.getMeasuredWidth();
int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(1000, View.MeasureSpec.AT_MOST);
copy.setLayoutParams(mContentView.getLayoutParams());
copy.measure(widthMeasureSpec, heightMeasureSpec);
return copy.getMeasuredHeight();
}
/**
* 折叠和展开
*/
private void expand() {
int startHeight;
int targetHeight;
if (!flag) {
flag = true;
startHeight = getMinMeasureHeight();
targetHeight = getMaxMeasureHeight();
if (targetHeight < startHeight) {
targetHeight = startHeight;
}
mHintView.setText(foldHint);
ObjectAnimator.ofFloat(mIndicateImage, "rotation", 0, 180).start();
if (mListener != null) {
mListener.onExpand();
}
} else {
flag = false;
startHeight = getMaxMeasureHeight();
targetHeight = getMinMeasureHeight();
if (startHeight < targetHeight) {
startHeight = targetHeight;
}
mHintView.setText(expandHint);
ObjectAnimator.ofFloat(mIndicateImage, "rotation", -180, 0).start();
if (mListener != null) {
mListener.onFold();
}
}
if (animationDuration < 0) {
animationDuration = DEFAULT_ANIMATION_DURATION;
}
final ViewGroup.LayoutParams layoutParams = mContentView.getLayoutParams();
ValueAnimator animator = ValueAnimator.ofInt(startHeight, targetHeight);
animator.setDuration(animationDuration);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
layoutParams.height = (int) animation.getAnimatedValue();
mContentView.setLayoutParams(layoutParams);
}
});
animator.start();
}
public interface OnReadMoreClickListener {
//点击了展开
void onExpand();
//点击了折叠
void onFold();
}
public static int dp2px(Context context, float dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, context.getResources().getDisplayMetrics());
}
public static int sp2px(Context context, float spVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
spVal, context.getResources().getDisplayMetrics());
}
public static float px2dp(Context context, float pxVal) {
final float scale = context.getResources().getDisplayMetrics().density;
return (pxVal / scale);
}
public static float px2sp(Context context, float pxVal) {
return (pxVal / context.getResources().getDisplayMetrics().scaledDensity);
}
}
attrs.xml
<resources>
<declare-styleable name="ExpandTextView">
<attr name="titleText" format="reference|string" />
<attr name="contentText" format="reference|string" />
<attr name="foldHint" format="reference|string" />
<attr name="expandHint" format="reference|string" />
<attr name="textTitleColor" format="reference|color" />
<attr name="textContentColor" format="reference|color" />
<attr name="textHintColor" format="reference|color" />
<attr name="indicateImage" format="reference" />
<attr name="minVisibleLines" format="integer" />
<attr name="titleTextSize" format="dimension" />
<attr name="contentTextSize" format="dimension" />
<attr name="hintTextSize" format="dimension" />
<attr name="animationDuration" format="integer" />
</declare-styleable>
</resources>
2、使用方法
etv.setContent("在这里输入textview需要显示的内容");
// etv.setHintTextColor(Color.parseColor("#913242"));
etv.setAnimationDuration(10000);
// etv.setIndicateImage(R.drawable.aaa);
etv.setOnReadMoreListener(new ExpandTextView.OnReadMoreClickListener() {
@Override
public void onExpand() {
Toast.makeText(EnterActivity.this, "expand", Toast.LENGTH_SHORT).show();
}
@Override
public void onFold() {
Toast.makeText(EnterActivity.this, "fold", Toast.LENGTH_SHORT).show();
}
});
3、第二种,可设置展开全文的位置。
引用:
https://github.com/zly394/CollapsedTextView
public class CollapsedTextView extends AppCompatTextView implements View.OnClickListener {
/**
* 末尾省略号
*/
private static final String ELLIPSE = "...";
/**
* 默认的折叠行数
*/
public static final int COLLAPSED_LINES = 4;
/**
* 折叠时的默认文本
*/
private static final String EXPANDED_TEXT = "展开全文";
/**
* 展开时的默认文本
*/
private static final String COLLAPSED_TEXT = "收起全文";
/**
* 在文本末尾
*/
public static final int END = 0;
/**
* 在文本下方
*/
public static final int BOTTOM = 1;
/**
* 提示文字展示的位置
*/
@IntDef({END, BOTTOM})
@Retention(RetentionPolicy.SOURCE)
public @interface TipsGravityMode {
}
/**
* 折叠的行数
*/
private int mCollapsedLines;
/**
* 折叠时的文本
*/
private String mExpandedText;
/**
* 展开时的文本
*/
private String mCollapsedText;
/**
* 折叠时的图片资源
*/
private Drawable mExpandedDrawable;
/**
* 展开时的图片资源
*/
private Drawable mCollapsedDrawable;
/**
* 原始的文本
*/
private CharSequence mOriginalText;
/**
* TextView中文字可显示的宽度
*/
private int mShowWidth;
/**
* 是否是展开的
*/
private boolean mIsExpanded;
/**
* 提示文字位置
*/
private int mTipsGravity;
/**
* 提示文字颜色
*/
private int mTipsColor;
/**
* 提示文字是否显示下划线
*/
private boolean mTipsUnderline;
/**
* 提示是否可点击
*/
private boolean mTipsClickable;
/**
* 提示文本的点击事件
*/
private ExpandedClickableSpan mClickableSpan = new ExpandedClickableSpan();
/**
* TextView的点击事件监听
*/
private OnClickListener mListener;
/**
* 是否响应TextView的点击事件
*/
private boolean mIsResponseListener = true;
public CollapsedTextView(Context context) {
this(context, null);
}
public CollapsedTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CollapsedTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs);
// 使点击有效
setMovementMethod(LinkMovementMethod.getInstance());
}
/**
* 初始化属性
*/
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
TypedArray typed = context.obtainStyledAttributes(attrs, R.styleable.CollapsedTextView);
mCollapsedLines = typed.getInt(R.styleable.CollapsedTextView_collapsedLines, COLLAPSED_LINES);
setExpandedText(typed.getString(R.styleable.CollapsedTextView_expandedText));
setCollapsedText(typed.getString(R.styleable.CollapsedTextView_collapsedText));
setExpandedDrawable(typed.getDrawable(R.styleable.CollapsedTextView_expandedDrawable));
setCollapsedDrawable(typed.getDrawable(R.styleable.CollapsedTextView_collapsedDrawable));
mTipsGravity = typed.getInt(R.styleable.CollapsedTextView_tipsGravity, END);
mTipsColor = typed.getColor(R.styleable.CollapsedTextView_tipsColor, 0);
mTipsUnderline = typed.getBoolean(R.styleable.CollapsedTextView_tipsUnderline, false);
mTipsClickable = typed.getBoolean(R.styleable.CollapsedTextView_tipsClickable, true);
typed.recycle();
}
}
/**
* 设置折叠行数
*
* @param collapsedLines 折叠行数
*/
public void setCollapsedLines(@IntRange(from = 0) int collapsedLines) {
this.mCollapsedLines = collapsedLines;
}
/**
* 设置折叠时的提示文本
*
* @param expandedText 提示文本
*/
public void setExpandedText(String expandedText) {
this.mExpandedText = TextUtils.isEmpty(expandedText) ? EXPANDED_TEXT : expandedText;
}
/**
* 设置展开时的提示文本
*
* @param collapsedText 提示文本
*/
public void setCollapsedText(String collapsedText) {
this.mCollapsedText = TextUtils.isEmpty(collapsedText) ? COLLAPSED_TEXT : collapsedText;
}
/**
* 设置折叠时的提示图片
*
* @param resId 图片资源
*/
public void setExpandedDrawableRes(@DrawableRes int resId) {
setExpandedDrawable(ContextCompat.getDrawable(getContext(), resId));
}
/**
* 设置折叠时的提示图片
*
* @param expandedDrawable 图片
*/
public void setExpandedDrawable(Drawable expandedDrawable) {
if (expandedDrawable != null) {
this.mExpandedDrawable = expandedDrawable;
this.mExpandedDrawable.setBounds(0, 0, mExpandedDrawable.getIntrinsicWidth(), mExpandedDrawable.getIntrinsicHeight());
}
}
/**
* 设置展开时的提示图片
*
* @param resId 图片资源
*/
public void setCollapsedDrawableRes(@DrawableRes int resId) {
setCollapsedDrawable(ContextCompat.getDrawable(getContext(), resId));
}
/**
* 设置展开时的提示图片
*
* @param collapsedDrawable 图片
*/
public void setCollapsedDrawable(Drawable collapsedDrawable) {
if (collapsedDrawable != null) {
this.mCollapsedDrawable = collapsedDrawable;
this.mCollapsedDrawable.setBounds(0, 0, mCollapsedDrawable.getIntrinsicWidth(), mCollapsedDrawable.getIntrinsicHeight());
}
}
/**
* 设置提示的位置
*
* @param tipsGravity END 表示在文字末尾,BOTTOM 表示在文字下方
*/
public void setTipsGravity(@TipsGravityMode int tipsGravity) {
this.mTipsGravity = tipsGravity;
}
/**
* 设置文字提示的颜色
*
* @param tipsColor 颜色
*/
public void setTipsColor(@ColorInt int tipsColor) {
this.mTipsColor = tipsColor;
}
/**
* 设置提示文字是否有下划线
*
* @param tipsUnderline true 表示有下划线
*/
public void setTipsUnderline(boolean tipsUnderline) {
this.mTipsUnderline = tipsUnderline;
}
/**
* 设置提示文字是否可点击
*
* @param tipsClickable true 表示可点击
*/
public void setTipsClickable(boolean tipsClickable) {
this.mTipsClickable = tipsClickable;
}
@Override
public void setText(final CharSequence text, final BufferType type) {
// 如果text为空或mCollapsedLines为0则直接显示
if (TextUtils.isEmpty(text) || mCollapsedLines == 0) {
super.setText(text, type);
} else if (mIsExpanded) {
// 保存原始文本,去掉文本末尾的空字符
this.mOriginalText = trimFrom(text);
formatExpandedText(type);
} else {
// 获取TextView中文字显示的宽度,需要在layout之后才能获取到,避免重复获取
if (mShowWidth == 0) {
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
getViewTreeObserver().removeOnGlobalLayoutListener(this);
mShowWidth = getWidth() - getPaddingLeft() - getPaddingRight();
formatCollapsedText(type, text);
}
});
} else {
formatCollapsedText(type, text);
}
}
}
/**
* 格式化折叠时的文本
*
* @param type ref android.R.styleable#TextView_bufferType
*/
private void formatCollapsedText(BufferType type, CharSequence text) {
// 保存原始文本,去掉文本末尾的空字符
this.mOriginalText = trimFrom(text);
// 获取 layout,用于计算行数
Layout layout = getLayout();
// 调用 setText 用于重置 Layout
if (layout == null || !layout.getText().equals(mOriginalText)) {
super.setText(mOriginalText, type);
layout = getLayout();
}
// 获取 paint,用于计算文字宽度
TextPaint paint = getPaint();
int line = layout.getLineCount();
if (line <= mCollapsedLines) {
super.setText(mOriginalText, type);
} else {
// 最后一行的开始字符位置
int lastLineStart = layout.getLineStart(mCollapsedLines - 1);
// 最后一行的结束字符位置
int lastLineEnd = layout.getLineVisibleEnd(mCollapsedLines - 1);
// 计算后缀的宽度
int expandedTextWidth;
if (mTipsGravity == END) {
expandedTextWidth = (int) paint.measureText(ELLIPSE + " " + mExpandedText);
} else {
expandedTextWidth = (int) paint.measureText(ELLIPSE + " ");
}
// 最后一行的宽
float lastLineWidth = layout.getLineWidth(mCollapsedLines - 1);
// 如果大于屏幕宽度则需要减去部分字符
if (lastLineWidth + expandedTextWidth > mShowWidth) {
int cutCount = paint.breakText(mOriginalText, lastLineStart, lastLineEnd, false, expandedTextWidth, null);
lastLineEnd -= cutCount;
}
// 因设置的文本可能是带有样式的文本,如SpannableStringBuilder,所以根据计算的字符数从原始文本中截取
SpannableStringBuilder spannable = new SpannableStringBuilder();
// 截取文本,还是因为原始文本的样式原因不能直接使用paragraphs中的文本
CharSequence ellipsizeText = mOriginalText.subSequence(0, lastLineEnd);
spannable.append(ellipsizeText);
spannable.append(ELLIPSE);
// 设置样式
setSpan(spannable);
super.setText(spannable, type);
}
}
/**
* 格式化展开式的文本,直接在后面拼接即可
*
* @param type
*/
private void formatExpandedText(BufferType type) {
SpannableStringBuilder spannable = new SpannableStringBuilder(mOriginalText);
setSpan(spannable);
super.setText(spannable, type);
}
/**
* 设置提示的样式
*
* @param spannable 需修改样式的文本
*/
private void setSpan(SpannableStringBuilder spannable) {
Drawable drawable;
// 根据提示文本需要展示的文字拼接不同的字符
if (mTipsGravity == END) {
spannable.append(" ");
} else {
spannable.append("\n");
}
int tipsLen;
// 判断是展开还是收起
if (mIsExpanded) {
spannable.append(mCollapsedText);
drawable = mCollapsedDrawable;
tipsLen = mCollapsedText.length();
} else {
spannable.append(mExpandedText);
drawable = mExpandedDrawable;
tipsLen = mExpandedText.length();
}
// 设置点击事件
spannable.setSpan(mClickableSpan, spannable.length() - tipsLen,
spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
// 如果提示的图片资源不为空,则使用图片代替提示文本
if (drawable != null) {
spannable.setSpan(new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE),
spannable.length() - tipsLen, spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
spannable.append(" ");
}
}
@Override
public void setOnClickListener(@Nullable OnClickListener l) {
// 保存TextView的点击监听事件
this.mListener = l;
super.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (!mIsResponseListener) {
// 如果不响应TextView的点击事件,将属性置为true
mIsResponseListener = true;
} else if (mListener != null) {
// 如果响应TextView的点击事件且监听不为空,则响应点击事件
mListener.onClick(v);
}
}
/**
* 提示的点击事件
*/
private class ExpandedClickableSpan extends ClickableSpan {
@Override
public void onClick(View widget) {
// 是否可点击
if (mTipsClickable) {
mIsResponseListener = false;
mIsExpanded = !mIsExpanded;
setText(mOriginalText);
}
}
@Override
public void updateDrawState(TextPaint ds) {
// 设置提示文本的颜色和是否需要下划线
ds.setColor(mTipsColor == 0 ? ds.linkColor : mTipsColor);
ds.setUnderlineText(mTipsUnderline);
}
}
/**
* 去掉空白字符,这里只去掉了尾部的空白字符
*
* @param sequence 需处理的字符
* @return 处理过的字符
*/
public static CharSequence trimFrom(CharSequence sequence) {
int len = sequence.length();
int first = 0;
int last;
// for (first = 0; first < len; first++) {
// if (!matches(sequence.charAt(first))) {
// break;
// }
// }
for (last = len - 1; last > first; last--) {
if (!matches(sequence.charAt(last))) {
break;
}
}
return sequence.subSequence(first, last + 1);
}
private static boolean matches(char c) {
switch (c) {
case '\t':
case '\n':
case '\013':
case '\f':
case '\r':
case ' ':
case '\u0085':
case '\u1680':
case '\u2028':
case '\u2029':
case '\u205f':
case '\u3000':
return true;
case '\u2007':
return false;
default:
return c >= '\u2000' && c <= '\u200a';
}
}
}
<declare-styleable name="CollapsedTextView">
<attr name="collapsedLines" format="integer" />
<attr name="expandedText" format="string" />
<attr name="collapsedText" format="string" />
<attr name="expandedDrawable" format="reference" />
<attr name="collapsedDrawable" format="reference" />
<attr name="tipsGravity">
<flag name="end" value="0" />
<flag name="bottom" value="1" />
</attr>
<attr name="tipsColor" format="reference|color" />
<attr name="tipsUnderline" format="boolean" />
<attr name="tipsClickable" format="boolean" />
</declare-styleable>