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移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
学习分享
在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了
很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘
如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。
2021最新上万页的大厂面试真题
七大模块学习资料:如NDK模块开发、Android框架体系架构…
2021大厂面试真题:
只有系统,有方向的学习,才能在短时间内迅速提高自己的技术,只有不断地学习,不懈的努力才能拥有更好的技术,才能在互联网行业中立于不败之地。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
5)]
[外链图片转存中…(img-kWfyOS9Y-1713305639476)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
学习分享
在当下这个信息共享的时代,很多资源都可以在网络上找到,只取决于你愿不愿意找或是找的方法对不对了
很多朋友不是没有资料,大多都是有几十上百个G,但是杂乱无章,不知道怎么看从哪看起,甚至是看后就忘
如果大家觉得自己在网上找的资料非常杂乱、不成体系的话,我也分享一套给大家,比较系统,我平常自己也会经常研读。
2021最新上万页的大厂面试真题
[外链图片转存中…(img-D2bJO1DC-1713305639477)]
七大模块学习资料:如NDK模块开发、Android框架体系架构…
[外链图片转存中…(img-SqHtAfwi-1713305639478)]
2021大厂面试真题:
[外链图片转存中…(img-nqm5tYTj-1713305639479)]
只有系统,有方向的学习,才能在短时间内迅速提高自己的技术,只有不断地学习,不懈的努力才能拥有更好的技术,才能在互联网行业中立于不败之地。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!