ExpandableTextView——一个可折叠的Textview

private int drawableWidth;

//提示图标的高度

private int drawableHeight;

//最大显示文本行对应的本视图高度

private int maxLinesHeight;

//展开时候的视图高度

private int expandHeight;

//当前视图的高度

private int viewHeight;

//收缩行结尾提示语文本宽度

private float ellipsizWidth;

//收缩行结尾提示语文本绘制水平起点

private float ellipsizStartX;

//文本字体大小

private int textSize;

//文本颜色

private int textColor;

//当前文本

private String text;

private String ellipsizText = “…”;

//收缩行文本

private String shrinkLineText;

//动画显示时间

private int animDuration;

//是否能够显示 ellipsizText 【需要收缩行当前文本的宽度】

private boolean showEllipsizText = false;

private boolean showTipDrawalbe = false;

private boolean needMeasure = true;

private StaticLayout layout;

private TextPaint textPaint;

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);

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ExpandTextView);

My_maxLines = ta.getInt(R.styleable.ExpandTextView_My_maxLines, -1);

animDuration = ta.getInt(R.styleable.ExpandTextView_animDuration, 300);

textSize = ta.getDimensionPixelSize(R.styleable.ExpandTextView_textSize, 14);

textColor = ta.getColor(R.styleable.ExpandTextView_textColor, 14);

drawableWidth = ta.getDimensionPixelSize(R.styleable.ExpandTextView_drawableWidth, 14);

drawableHeight = ta.getDimensionPixelSize(R.styleable.ExpandTextView_drawableHeight, 14);

expandDrawable = ta.getDrawable(R.styleable.ExpandTextView_expandDrawable);

shrinkDrawable = ta.getDrawable(R.styleable.ExpandTextView_shrinkDrawable);

ta.recycle();

textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);

textPaint.density = context.getResources().getDisplayMetrics().density;

textPaint.setColor(textColor);

textPaint.setStyle(Paint.Style.FILL_AND_STROKE);

textPaint.setTextSize(textSize);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int width = MeasureSpec.getSize(widthMeasureSpec);

if (needMeasure && (!TextUtils.isEmpty(text))) {

needMeasure = false;

measureHeightState(text, width);

startDrawAnim(0, viewHeight);

}else{

heightMeasureSpec = MeasureSpec.makeMeasureSpec(viewHeight, MeasureSpec.EXACTLY);

setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);

}

}

public void updateText(String text) {

if (!TextUtils.isEmpty(text)) {

this.text = text;

needMeasure = true;

requestLayout();

}

}

private synchronized void measureHeightState(String text, int width) {

layout = new StaticLayout(text, textPaint, width - getPaddingLeft() - getPaddingRight(), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0f, true);

final int lineCount = layout.getLineCount();

My_maxLines = (My_maxLines == -1 || My_maxLines > lineCount) ? lineCount : My_maxLines;

int text_Height = 0;

List tempLines = new ArrayList();

for (int index = 0; index < lineCount; index++) {

int start = layout.getLineStart(index);

int end = layout.getLineEnd(index);

LineText lineText = new LineText();

lineText.setStartIndex(start);

lineText.setEndIndex(end - 1);

lineText.setText(text.substring(start, end));

lineText.setTopOffset(layout.getLineTop(index));

lineText.setBottomOffset(layout.getLineBottom(index));

lineText.setBaseLine(layout.getLineBaseline(index)+getPaddingTop());

lineText.setWidth(layout.getLineWidth(index));

lineText.setHeight(lineText.getBottomOffset() - lineText.getTopOffset());

tempLines.add(lineText);

if (index < My_maxLines) {

maxLinesHeight += lineText.getHeight();

}

text_Height += lineText.getHeight();

}

maxLinesHeight+=getPaddingTop()+getPaddingBottom();

expandHeight+=getPaddingTop()+getPaddingBottom();

ellipsizWidth = textPaint.measureText(ellipsizText);

if (My_maxLines < lineCount) {

showTipDrawalbe = expandDrawable != null && shrinkDrawable != null;

float textWidth = tempLines.get(My_maxLines - 1).getWidth();

float contentWidth = width - getPaddingLeft() - getPaddingRight();

float toMarginRight = ellipsizWidth + (showTipDrawalbe ? drawableWidth : 0);

String ellipsizLineText = tempLines.get(My_maxLines - 1).getText();

if (contentWidth - textWidth < toMarginRight) {

showEllipsizText = true;

String subString = null;

for (int index = ellipsizLineText.length() - 1; index > 0; index–) {

subString = ellipsizLineText.substring(0, index);

float subStrWidth = textPaint.measureText(subString);

if (contentWidth - subStrWidth >= toMarginRight) {

ellipsizStartX = subStrWidth + getPaddingLeft();

shrinkLineText = subString;

break;

}

}

} else {

shrinkLineText = ellipsizLineText;

showEllipsizText = false;

}

} else {

showTipDrawalbe = false;

showEllipsizText = false;

}

expandHeight += text_Height + ((expandDrawable != null && showTipDrawalbe) ? drawableHeight : 0);

viewHeight = My_maxLines == lineCount ? expandHeight : maxLinesHeight;

targetLine = My_maxLines;

lineTexts = tempLines;

if (viewHeight < expandHeight) {

setClickable(true);

setOnClickListener(this);

} else {

setClickable(false);

}

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

if (lineTexts.size() == 0) return;

for (int index = 0; index < targetLine; index++) {

LineText lineText = lineTexts.get(index);

if (index < targetLine - 1) {

canvas.drawText(lineText.getText(), getPaddingLeft(), lineText.getBaseLine(), textPaint);

} else {

if (targetLine == My_maxLines && My_maxLines < lineTexts.size()) {

//收缩转态

if (showEllipsizText)

canvas.drawText(ellipsizText, ellipsizStartX, lineText.getBaseLine(), textPaint);

canvas.drawText(shrinkLineText, getPaddingLeft(), lineText.getBaseLine(), textPaint);

if (showTipDrawalbe){

int left=getWidth() - drawableWidth - getPaddingRight();

int top=getHeight() - drawableHeight-getPaddingBottom();

canvas.drawBitmap(drawabletoZoomBitmap(shrinkDrawable, drawableWidth, drawableHeight), left, top, null);

}

} else if (targetLine == lineTexts.size()) {

//展开状态

canvas.drawText(lineText.getText(), getPaddingLeft(), lineText.getBaseLine(), textPaint);

if (showTipDrawalbe){

int left=getWidth() - drawableWidth - getPaddingRight();

int top=getHeight() - drawableHeight-getPaddingBottom();

canvas.drawBitmap(drawabletoZoomBitmap(expandDrawable, drawableWidth, drawableHeight), left, top, null);

}

}

}

}

}

@Override

public void onClick(View view) {

if (My_maxLines == lineTexts.size())

return;

if (targetLine == My_maxLines) {

targetLine = lineTexts.size();

startDrawAnim(maxLinesHeight, expandHeight);

} else if (targetLine == lineTexts.size()) {

targetLine = My_maxLines;

startDrawAnim(expandHeight, maxLinesHeight);

}

}

private void startDrawAnim(int startHeight, int endHeight) {

ObjectAnimator animator = ObjectAnimator.ofInt(this, “viewHeight”, startHeight, endHeight);

animator.setDuration(animDuration);

// animator.setInterpolator(new AccelerateDecelerateInterpolator());

animator.start();

}

public int getViewHeight() {

return viewHeight;

}

public void setViewHeight(int viewHeight) {

this.viewHeight = viewHeight;

requestLayout();

}

public String getText() {

return text;

}

public void setText(String text) {

this.text = text;

}

/**

  • drawlable 缩放

  • @return

*/

public static Bitmap drawabletoZoomBitmap(Drawable drawable, int w, int h) {

// 取 drawable 的长宽

int width = drawable.getIntrinsicWidth();

int height = drawable.getIntrinsicHeight();

// drawable转换成bitmap

Bitmap oldbmp = drawabletoBitmap(drawable);

// 创建操作图片用的Matrix对象

Matrix matrix = new Matrix();

// 计算缩放比例

float sx = ((float) w / width);

float sy = ((float) h / height);

// 设置缩放比例

matrix.postScale(sx, sy);

// 建立新的bitmap,其内容是对原bitmap的缩放后的图

Bitmap newbmp = Bitmap.createBitmap(oldbmp, 0, 0, width, height,

matrix, true);

return newbmp;

}

/**

  • Drawable转换成Bitmap

*/

public static Bitmap drawabletoBitmap(Drawable drawable) {

// 取 drawable 的长宽

int width = drawable.getIntrinsicWidth();

int height = drawable.getIntrinsicHeight();

// 取 drawable 的颜色格式

Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
Bitmap.Config.RGB_565;

Bitmap bitmap = Bitmap.createBitmap(width, height, config);

Canvas canvas = new Canvas(bitmap);

drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),

drawable.getIntrinsicHeight());

drawable.draw(canvas);

return bitmap;

}

}

lineText.java

package com.toolbar;

/**

  • Created by igeek on 2016/9/1.

  • @author igeek2014@hotmail.com

*/

public class LineText {

private String text;

private int startIndex;

private int endIndex;

private int lineIndex;

private int topOffset;

private int bottomOffset;

private int paddingTop;

private int paddingBottom;

private float width;

private int height;

private int baseLine;

public String getText() {

return text;

}

public void setText(String text) {

this.text = text;

}

public int getStartIndex() {

return startIndex;

}

public void setStartIndex(int startIndex) {

this.startIndex = startIndex;

}

public int getEndIndex() {

return endIndex;

}

public void setEndIndex(int endIndex) {

this.endIndex = endIndex;

}

public int getLineIndex() {

return lineIndex;

}

public void setLineIndex(int lineIndex) {

this.lineIndex = lineIndex;

}

public int getTopOffset() {

return topOffset;

}

public void setTopOffset(int topOffset) {

this.topOffset = topOffset;

}

public int getPaddingTop() {

return paddingTop;

}

public void setPaddingTop(int paddingTop) {

this.paddingTop = paddingTop;

}

public int getPaddingBottom() {

return paddingBottom;

}

public void setPaddingBottom(int paddingBottom) {

this.paddingBottom = paddingBottom;

}

public float getWidth() {

return width;

}

public void setWidth(float width) {

this.width = width;

}

public int getHeight() {

return height;

}

public void setHeight(int height) {

this.height = height;

}

public int getBaseLine() {

return baseLine;

}

public void setBaseLine(int baseLine) {

this.baseLine = baseLine;

}

public int getBottomOffset() {

return bottomOffset;

}

public void setBottomOffset(int bottomOffset) {

this.bottomOffset = bottomOffset;

}

}

<com.toolbar.ExpandTextView

android:id=“@+id/collapsing_text”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:layout_marginTop=“12dp”

android:paddingLeft=“8dp”

android:paddingRight=“8dp”

android:paddingBottom=“8dp”

最后看一下学习需要的所有知识点的思维导图。在刚刚那份学习笔记里包含了下面知识点所有内容!文章里已经展示了部分!如果你正愁这块不知道如何学习或者想提升学习这块知识的学习效率,那么这份学习笔记绝对是你的秘密武器!


《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

}

public int getBaseLine() {

return baseLine;

}

public void setBaseLine(int baseLine) {

this.baseLine = baseLine;

}

public int getBottomOffset() {

return bottomOffset;

}

public void setBottomOffset(int bottomOffset) {

this.bottomOffset = bottomOffset;

}

}

<com.toolbar.ExpandTextView

android:id=“@+id/collapsing_text”

android:layout_width=“match_parent”

android:layout_height=“wrap_content”

android:layout_marginTop=“12dp”

android:paddingLeft=“8dp”

android:paddingRight=“8dp”

android:paddingBottom=“8dp”

最后看一下学习需要的所有知识点的思维导图。在刚刚那份学习笔记里包含了下面知识点所有内容!文章里已经展示了部分!如果你正愁这块不知道如何学习或者想提升学习这块知识的学习效率,那么这份学习笔记绝对是你的秘密武器!

[外链图片转存中…(img-BWzLbUrb-1714807338776)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 8
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值