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”
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021最新上万页的大厂面试真题

image

七大模块学习资料:如NDK模块开发、Android框架体系架构…

image

2021大厂面试真题:

image

只有系统,有方向的学习,才能在短时间内迅速提高自己的技术,只有不断地学习,不懈的努力才能拥有更好的技术,才能在互联网行业中立于不败之地。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

5)]

[外链图片转存中…(img-kWfyOS9Y-1713305639476)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

学习分享

在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了

很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘

如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。

2021最新上万页的大厂面试真题

[外链图片转存中…(img-D2bJO1DC-1713305639477)]

七大模块学习资料:如NDK模块开发、Android框架体系架构…

[外链图片转存中…(img-SqHtAfwi-1713305639478)]

2021大厂面试真题:

[外链图片转存中…(img-nqm5tYTj-1713305639479)]

只有系统,有方向的学习,才能在短时间内迅速提高自己的技术,只有不断地学习,不懈的努力才能拥有更好的技术,才能在互联网行业中立于不败之地。

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 30
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值