这里提供一个间接的方法,通过StaticLayout来间接获取行数。 staticLayout; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { staticLayout = getStaticLayout23 (textView, width); } else { staticLayout = getStaticLayout(textView, width); } int lines = staticLayout.getLineCount(); int maxLines = textView.getMaxLines(); if (maxLines > lines getStaticLayout23(TextView textView, int width) { StaticLayout.Builder builder = StaticLayout.Builder.obtain
StaticLayout的使用场景为多行文本的渲染和SpannableString的渲染。 width = staticLayout.getLineWidth(0) val height = staticLayout.height Log.d("xys", "line width $width 如果是API26+,可以使用新的API构造StaticLayout,代码如下所示。 // API 26+ val staticLayout = StaticLayout.Builder .obtain(text, start, end, textPaint, width 关于StaticLayout这里有一篇比较好的文章推荐给大家。
如何获取超过限制行数最后一个文字的下标 解决以上两个问题需要用到一个处理TextView文本排版,拆行处理的工具类SaticLayout,SaticLayout构造函数很多,但最终回调用这个构造函数 public StaticLayout 如果需要详细了解StaticLayout的工作原理,可参考StaticLayout 源码分析 然后我们可以通过调用getLineCount()方法获取到布局该文本的行数,调用getLineStart(int 传入相应参数 StaticLayout staticLayout = new StaticLayout(content,paint,width, Layout.Alignment.ALIGN_NORMAL , 1, 0, false); //判断content是行数是否超过最大限制行数3行 if (staticLayout.getLineCount()>maxLine) { //以上代码省略 //计算得出contentview最后展开的高度 expandHeight= staticLayout.getHeight() + tv.getPaddingTop(
= layout.getLineStart(i); int lineEnd = layout.getLineEnd(i); float width = StaticLayout.getDesiredWidth String blanks = " "; canvas.drawText(blanks, x, mLineY, getPaint()); float bw = StaticLayout.getDesiredWidth line.charAt(1) == 12288) { String substring = line.substring(0, 2); float cw = StaticLayout.getDesiredWidth line.length(); i++) { String c = String.valueOf(line.charAt(i)); float cw = StaticLayout.getDesiredWidth
android.text.TextUtils.indexOf(TextUtils.java:102) 04-29 02:53:44.654: E/AndroidRuntime(326): at android.text.StaticLayout.generate (StaticLayout.java:131) 04-29 02:53:44.654: E/AndroidRuntime(326): at android.text.StaticLayout. <init>(StaticLayout.java:97) 04-29 02:53:44.654: E/AndroidRuntime(326): at android.text.StaticLayout. <init>(StaticLayout.java:54) 04-29 02:53:44.654: E/AndroidRuntime(326): at android.text.StaticLayout. <init>(StaticLayout.java:45) 04-29 02:53:44.654: E/AndroidRuntime(326): at android.widget.TextView.makeNewLayout
adapter.notifyItemRangeChanged(positionStart,itemcount) TextView 优化 原因:面对复杂文本性能不佳 方案: - BoringLayout 单行 - StaticLayout 多行 - DynamicLayout 可编辑展示文本 - 展示类StaticLayout即可,性能优于DynamicLayout - 异步创建StaticLayout public class CustomTextView extends View { private String mText = "我是StaticLayout显示出来的文本"; private TextPaint mTextPaint; private StaticLayout mStaticLayout; public CustomTextView(Context context) { Runnable() { @Override public void run() { mStaticLayout = new StaticLayout
1.4 StaticLayout 额外讲一个 StaticLayout。这个也是使用 Canvas 来进行文字的绘制,不过并不是使用 Canvas 的方法。 "; StaticLayout staticLayout1 = new StaticLayout(text1, paint, 600, Layout.Alignment.ALIGN_NORMAL , 1, 0, true); String text2 = "a\nbc\ndefghi\njklm\nnopqrst\nuvwx\nyz"; StaticLayout staticLayout2 = canvas.save(); canvas.translate(50, 100); staticLayout1.draw(canvas); canvas.translate(0, 200); staticLayout2 StaticLayout 的构造方法是 StaticLayout(CharSequence source, TextPaint paint, int width, Layout.Alignment align
先通过火焰图看看最耗时的调用栈是哪一条 图上可知ChangeWatcher.onSpanChanged()->ChangeWatcher.reflow()->DynamicLayout.reflow()->StaticLayout.generate 再看看调用顺序图 ChangeWatcher.onSpanChanged()被调用了多次,会多次调用DynamicLayout.reflow() DynamicLayout.reflow()中会调用多次StaticLayout.generate () 有一点疑问,我看DynamicLayout源码,每次reflow()应该只会调用一次StaticLayout.generate()而且都是在主线程,CallChat却显示了多次,而且调用次数没看出啥规律 ,不知道有没有大神可以帮我解下惑 BottomUp 其实通过上面两步基本已经定位到问题了,再在BottomUp的表格中确认一下 StaticLayout.generate()中有这样一段代码,这下实锤了 位置都发生了变化,每个ImageSpan变化都会触发一次ChangeWatcher.onSpanChanged()->ChangeWatcher.reflow()->DynamicLayout.reflow()->StaticLayout.generate
StaticLayout 布局容器 (1) StaticLayout 解析 StaticLayout 解析 : 该组件用于显示文本, 一旦该文本被显示后, 就不能再编辑, 如果想要修改文本, 使用 DynamicLayout itemsLayout == null || itemsLayout.getWidth() > widthItems) { /* * android.text.StaticLayout.StaticLayout getAdapter().getItem(currentItem) : null; valueLayout = new StaticLayout(text != null ? itemsLayout; private StaticLayout labelLayout; /** 选中条目布局 */ private StaticLayout valueLayout itemsLayout == null || itemsLayout.getWidth() > widthItems) { /* * android.text.StaticLayout.StaticLayout
textPaint.setTypeface(font); textPaint.setTextSize(22); // 这里是自动换行的 StaticLayout layout = new StaticLayout(title, textPaint, w, Alignment.ALIGN_NORMAL, 1.0F, 0.0F
} invalidate() } 03 drawText文字换行 如果用原有的要drawtext实现,那当传入的字符串很长时,后面的就显示不全了,所以这里改为用StaticLayout let { val builder = StaticLayout.Builder.obtain(it, 0, it.length, textpaint, width)
原因在于: 系统TextView真正排版及绘制的逻辑不在其本身,而是交给三个继承了Layout的子类负责,分别为StaticLayout、DynamicLayout、BoringLayout,我们更常用的是 StaticLayout,它只负责静态的文字处理,关于各自Layout的区别,这里了就不展开讲了。
PrecomputedTextCompat在9.0以上使用PrecomputedText优化,5.0~9.0使用StaticLayout优化,5.0以下的不做处理。
原理:span 是怎样工作的 Android 框架在数个类中涉及了文字样式处理以及 span:TextView、EditText、layout 类 (Layout、StaticLayout、DynamicLayout Layout 和两个子类,StaticLayout 和 DynamicLayout, 检查设置给文字的 span 并计算行高和布局 margin。
TextView, EditText, 布局类(Layout, StaticLayout , DynamicLayout)和TextLine(Layout中使用的一个私有类),它取决于下面几个参数: 文本类型 Layout以及它的两个子类StaticLayout和DynamicLayout,检查设置在文本上的Span来计算行高和布局边距。
android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) { val builder = StaticLayout.Builder.obtain
For text that will not change, use a {@link StaticLayout}.
For text that will not change, use a {@link StaticLayout}.
一种从文本字符串获取换行位置的方法 与Android和iOS的比较 在Android中,尽管大多数人会使用TextView,但是您可以通过使用StaticLayout,Canvas和Paint类获得低级控件来执行上面列出的所有操作
register_android_content_XmlBlock), REG_JNI(register_android_text_AndroidCharacter), REG_JNI(register_android_text_StaticLayout