我是靠谱客的博主 超帅薯片,这篇文章主要介绍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做截取

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部