我是靠谱客的博主 超帅薯片,最近开发中收集的这篇文章主要介绍StaticTextView ---TextView优化StaticTextView —TextView优化,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

StaticTextView —TextView优化

最近项目在做RecycerView的相关优化工作,发现系统提供的TextView效率不够高,setText方法每次总会消耗大概3-5ms左右,TextView作为很多view的基类,处理了很多事情比如文字变化的监听等,大大影响了bindViewHolder的时间,所以自定义了一个功能简化的TextView。

由于不需要其它特殊的功能支持,比如富文本等等,只需要提供简单的文字展示,所以使用StaticLayout去实现文字的layout控制,TextView内部有DynamicLayout、BoringLayout、StaticLayout三种,分别支持动态文本,单行文本,多行文本。

因为需要适配低版本android,StaticLayout在低版本安卓不支持builder创建,没有maxlines,ellipse相关属性,所以通过代码去实现maxline效果,对text做截取

public class StaticTextView extends View {
//行文本记录集
private List<LineText> lineTexts = new ArrayList<>();
//最大显示文本行数
private int mMaxLines = 2;
//最大显示文本行对应的本视图高度
private int maxLinesHeight;
//当前文本
private String mText;
private boolean needMeasure = true;
private TextPaint mTextPaint;
public StaticTextView(Context context) {
this(context, null);
}
public StaticTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public StaticTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initFontSize();
}
private void initFontSize() {
if (isInEditMode()) {
return;
}
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setTypeface(Typeface.create("sans-serif-medium", Typeface.NORMAL));
mTextPaint.density = getContext().getResources().getDisplayMetrics().density;
mTextPaint.setColor(Color.BLACK);
mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mTextPaint.setTextSize(UIUtils.sp2px(getContext(), 18f));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
if (needMeasure && (!TextUtils.isEmpty(mText))) {
needMeasure = false;
measureHeightState(mText, width);
} else {
setMeasuredDimension(width, maxLinesHeight);
}
}
public void setMaxLines(int maxLines) {
mMaxLines = maxLines;
needMeasure = true;
requestLayout();
invalidate();
}
public int getMaxLines() {
return mMaxLines;
}
public void updateText(String text) {
if (!TextUtils.isEmpty(text)) {
this.mText = text;
needMeasure = true;
requestLayout();
invalidate();
}
}
private void measureHeightState(String text, int width) {
maxLinesHeight = 0;
String mEllipsizeText = "...";
StaticLayout layout = StaticLayoutManager.INSTANCE.getLayout(text);
if (layout == null) {
layout = getStaticLayout(text, width);
}
mTextPaint = layout.getPaint();
final int lineCount = layout.getLineCount();
List<LineText> tempLines = new ArrayList<>();
for (int index = 0; index < lineCount; index++) {
if (index < mMaxLines) {
int start = layout.getLineStart(index);
int end = layout.getLineEnd(index);
LineText lineText = new LineText();
lineText.text = text.substring(start, end);
lineText.baseLine = layout.getLineBaseline(index) + getPaddingTop();
lineText.width = layout.getLineWidth(index);
lineText.height = layout.getLineBottom(index) - layout.getLineTop(index);
tempLines.add(lineText);
maxLinesHeight += lineText.height;
}
}
maxLinesHeight += getPaddingTop() + getPaddingBottom();
if (mMaxLines < lineCount) {
float ellipsizeWidth = mTextPaint.measureText(mEllipsizeText);
float textWidth = tempLines.get(mMaxLines - 1).width;
float contentWidth = width - getPaddingLeft() - getPaddingRight();
if (contentWidth - textWidth < ellipsizeWidth) {
String subString = tempLines.get(mMaxLines - 1).text;
subString = subString.substring(0,subString.length() - mEllipsizeText.length());
for (int index = subString.length() - 1; index > 0; index--) {
subString = subString.substring(0, index);
float subStrWidth = mTextPaint.measureText(subString);
if (contentWidth - subStrWidth >= ellipsizeWidth) {
subString += mEllipsizeText;
tempLines.get(mMaxLines - 1).text = subString;
break;
}
}
} else {
tempLines.get(mMaxLines - 1).text += mEllipsizeText;
}
}
lineTexts = tempLines;
setMeasuredDimension(width - getPaddingLeft() - getPaddingRight(), maxLinesHeight);
}
private StaticLayout getStaticLayout(String text, int width) {
StaticLayout layout;
layout = new StaticLayout(text, mTextPaint,
width - getPaddingLeft() - getPaddingRight(),
Layout.Alignment.ALIGN_NORMAL, 1.0f, 0f, true);
StaticLayoutManager.INSTANCE.addLayout(text, layout);
return layout;
}
@Override
protected void onDraw(Canvas canvas) {
if (lineTexts.size() == 0) {
return;
}
for (int index = 0; index < lineTexts.size(); index++) {
LineText lineText = lineTexts.get(index);
canvas.drawText(lineText.text, getPaddingLeft(), lineText.baseLine,
mTextPaint);
}
}
public int getLineCount() {
return lineTexts.size();
}
public int getPaintFlags() {
return mTextPaint.getFlags();
}
public void setPaintFlags(int flag) {
if (mTextPaint.getFlags() != flag) {
mTextPaint.setFlags(flag);
needMeasure = true;
requestLayout();
invalidate();
}
}
public void setTextColor(int color) {
mTextPaint.setColor(color);
invalidate();
}
public class LineText {
public String text;
public float width;
public int height;
public int baseLine;
}
}

其中有一个StaticLayoutManager用来管理StaticLayout缓存,我会在异步解析后端数据的时候去提前创建StaticLayout,在onMeasure的时候直接从缓存里读取,缓存主要是一个LruCache

object StaticLayoutManager {
private val mLayoutList = LruCache<String, StaticLayout>(30)
fun getLayout(key: String): StaticLayout? {
return mLayoutList[key]
}
fun addLayout(paint: TextPaint, article: Article, width: Int) {
val text = article.mTitle
if (mLayoutList.get(text) != null || text.isEmpty()) {
return
}
val layout = StaticLayout(
text, paint, width,
Layout.Alignment.ALIGN_NORMAL, 1.0f, 0f, true
)
mLayoutList.put(text, layout)
}
fun addLayout(key: String, layout: StaticLayout) {
mLayoutList.put(key, layout)
}
}

https://github.com/ragnraok/StaticLayoutView
这个项目给出了另一种通过异步渲染的实现方案,可以参考

最后

以上就是超帅薯片为你收集整理的StaticTextView ---TextView优化StaticTextView —TextView优化的全部内容,希望文章能够帮你解决StaticTextView ---TextView优化StaticTextView —TextView优化所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(49)

评论列表共有 0 条评论

立即
投稿
返回
顶部