TextView 的 StaticLayout,比你想象中复杂点!

                <section class="" style="font-size: 15px;color: rgb(62, 62, 62);line-height: 2;word-spacing: 2px;letter-spacing: 2px;font-family: Vollkorn, Palatino, Times;padding-left: 0.2em;padding-right: 0.2em;text-align: justify;" data-mpa-powered-by="yiban.io"><section class="" data-mpa-template-id="913732" data-mpa-color="null" data-mpa-category="fav"><section data-id="us653081" class="" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;"><section class="" data-tools="135编辑器" data-id="90196" style="border-width: 0px;border-style: none;border-color: initial;box-sizing: border-box;"><section style="margin: 8px;padding: 10px;line-height: 25.6px;white-space: normal;border-radius: 10px;height: auto;box-shadow: rgb(221, 221, 221) 2px 2px 8px;display: -webkit-flex;box-sizing: border-box;"><section style="flex: 0 0 2cm;height: 78px;width:75px;"><img class="" data-copyright="0" data-cropselx1="0" data-cropselx2="76" data-cropsely1="0" data-cropsely2="76" data-ratio="1" data-src="https://mmbiz.qpic.cn/mmbiz_png/liaczD18OicSwHiaTHXJkJjwnfbCVkSd69RyohxZtQBmEnXwHmzpnKgq4coWC5tK9OshwNe43m6F1pN3UkPTRuWrQ/640" data-type="png" data-w="640" style="visibility: visible !important; width: 76px !important; height: auto !important;" _width="76px" src="https://mmbiz.qpic.cn/mmbiz_png/liaczD18OicSwHiaTHXJkJjwnfbCVkSd69RyohxZtQBmEnXwHmzpnKgq4coWC5tK9OshwNe43m6F1pN3UkPTRuWrQ/640?tp=webp&amp;wxfrom=5&amp;wx_lazy=1" data-fail="0"></section><section style="padding-right: 10px;padding-left: 10px;flex: 1 1 auto;height: 55px;box-sizing: border-box;"><section style="line-height: 35px;white-space: nowrap;text-align: justify;" class=""><strong mpa-from-tpl="t">承香墨影</strong></section><section style="line-height: 20px;text-align: justify;"><span style="color: rgb(191, 191, 191);font-size: 12px;">只分享最有用的原创技术干货!</span></section></section><section style="flex: 0 0 1.5cm;font-size: 15px;color: rgb(86, 187, 55);letter-spacing: 0px;text-align: center;line-height: 6;"><section style="margin-top: 25px;max-width: 100px;vertical-align: middle;border-width: 1px;border-style: solid;border-color: rgb(86, 187, 55);border-radius: 5px;box-sizing: border-box;"><section style="line-height: 2;letter-spacing: 0px;"><a href="http://mp.weixin.qq.com/s?__biz=MzIxNjc0ODExMA==&amp;mid=2247485094&amp;idx=2&amp;sn=56ee897e8a6c82f36e2d077fd1123b91&amp;chksm=97851f87a0f29691fac4d533c1f835e9cfb7b04c42cef5e1c4bb718421d573d7cbc07bf8b83b&amp;scene=21#wechat_redirect" target="_blank"><strong mpa-from-tpl="t"><span style="color: #00B050;">关注</span></strong></a></section></section></section></section></section></section></section><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><img class="" data-ratio="0.5555555555555556" data-src="https://mmbiz.qpic.cn/mmbiz_jpg/liaczD18OicSxPzCbnGx22LHt2MWlU1Az6nnDNXicBia5Ap04wBMmaVhuAyN2JUyNUQd9XhpK1ia76jB7Uvebpe5pAw/640" data-type="jpeg" data-w="900" style="font-size: inherit; color: inherit; line-height: inherit; display: block; margin-right: auto; margin-left: auto; border-style: none; border-radius: 0px; width: auto !important; height: auto !important; visibility: visible !important;" src="https://mmbiz.qpic.cn/mmbiz_jpg/liaczD18OicSxPzCbnGx22LHt2MWlU1Az6nnDNXicBia5Ap04wBMmaVhuAyN2JUyNUQd9XhpK1ia76jB7Uvebpe5pAw/640?tp=webp&amp;wxfrom=5&amp;wx_lazy=1" data-fail="0"></p><section class="" data-mpa-template-id="889566" data-mpa-color="null" data-mpa-category="fav"><section class=""><section powered-by="xiumi.us"><section style="margin-top: 10px;margin-bottom: 10px;"><section style="margin-bottom: -0.9em;margin-left: 0.5em;height: 1.4em;border-left: 1px solid rgb(158, 158, 158);" class=""><br></section><section style="width: 2.5em;border-top: 1px solid rgb(158, 158, 158);" class=""></section><section style="padding-right: 0.5em;padding-left: 0.5em;" class=""><section style="padding: 10px;"><section powered-by="xiumi.us" class=""><section><section><p style="text-align: justify;line-height: 1.5em;" class=""><span style="color:#888888;"><span style="font-size: 15px;letter-spacing: 0.5px;" mpa-is-content="t">在 Android 的众多控件中,我想 TextView 算是复杂度相对较高的一个控件了,内部包含了对文本内容的排版和折行等处理,并且本身也是很多控件的基类。而对于 TextView 的文本排版,会直接用到一个 Layout 类,而对于不同的场景,又会用 Layout 的不同子类来完成排版和布局。</span></span></p><p style="text-align: justify;line-height: 1.5em;" class=""><span style="color:#888888;"><span style="font-size: 15px;letter-spacing: 0.5px;" mpa-is-content="t">今天推荐的文章,就拿其中一个子类 StaticLayout ,来分析 TextView 是如何对静态文本进行布局和排版的。&nbsp;</span></span></p><p style="text-align: justify;line-height: 1.5em;" class=""><span style="color:#888888;"><span style="font-size: 15px;letter-spacing: 0.5px;" mpa-is-content="t"><br></span></span></p><p style="text-align: right;line-height: 1.5em;" class=""><span style="color:#888888;"><span style="font-size: 15px;letter-spacing: 0.5px;" mpa-is-content="t">— 承香墨影</span></span></p></section></section></section></section></section><section style="margin-left: auto;width: 2.5em;"><section style="width: 2.5em;border-top: 1px solid rgb(158, 158, 158);" class=""></section><section style="margin-top: -0.9em;margin-left: 2em;height: 1.4em;border-left: 1px solid rgb(158, 158, 158);"><br class=""></section></section></section></section></section></section><section class="" data-mpa-template-id="820333" data-mpa-color="null" data-mpa-category="fav"><section style="margin:30px auto;background-color:#f7f7f7;padding:25px 20px;"><section data-preserve-color="t" style="font-size:14px;color:#4f4f4f;" mpa-is-content="t"><span style="color: rgb(178, 178, 178);font-size: 12px;" mpa-is-content="t">作者 | 写代码的猴子</span></section><section data-preserve-color="t" style="font-size:14px;color:#4f4f4f;" mpa-is-content="t"><span style="color: rgb(178, 178, 178);font-size: 12px;" mpa-is-content="t">原文 | &lt;StaticLayout 源码分析&gt;</span></section><section data-preserve-color="t" style="font-size:14px;color:#4f4f4f;" mpa-is-content="t"><span style="color: rgb(178, 178, 178);font-size: 12px;" mpa-is-content="t">授权 承香墨影 发布</span></section></section></section><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">Android 中的文本布局和绘制都是由 Layout 类完成的,而 Layout 类一个重要的子类就是 StaticLayout 类,本文从源码来简单分析文本是如何布局的,具体如段落、折行处理以及省略方式的等等的处理。</p><h2 style="line-height: inherit;margin-top: 1.6em;font-size: 18px;margin-bottom: 20px;color: rgb(92, 172, 238);text-align: center;"><span style="font-size: inherit;color: inherit;line-height: inherit;border-bottom: 1px solid rgb(92, 172, 238);padding-left: 5px;padding-right: 5px;padding-bottom: 3px;">前言</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">Android 控件中,看起来最简单、最基础的 TextView 实际上是很复杂的,很多常见的控件都是其子类,例如 Botton、EditText、CheckBox 等,由于作为一个基础控件类,TextView 需要考虑到子类的各种使用场景,满足子类的需求。源码中,TextView 单个类源码就多达一万行,而且其工作时还依赖很多辅助类。其文本的排版、折行处理,以及最终的显示,均是交给辅助类 Layout 类来处理的。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">由于 Canvas 本身提供的 drawText 绘制文本是不支持换行的,所以在文本需要换行显示时,就需要用到 Layout 类。我们可以看到官方对 Layout 类的描述:</p><blockquote style="font-size: inherit;line-height: inherit;color: rgb(102, 102, 102);border-top: 1px solid rgb(221, 221, 221);border-right: 1px solid rgb(221, 221, 221);border-bottom: 1px solid rgb(221, 221, 221);border-left-color: rgb(92, 172, 238);background-color: rgb(255, 255, 255);border-radius: 2px;padding-left: 20px;padding-right: 20px;margin-top: 0.8em;margin-bottom: 0.8em;"><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">A base class that manages text layout in visual elements on the screen.</p></blockquote><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">一个用于管理屏幕上文本布局的基类。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">其直接子类有 StaticLayout、DynamicLayout、BoringLayout,在官方的文档中提到,如果文本内容会被编辑,应该使用 DynamicLayout,如果文本显示之后不会发生改变,应该使用 StaticLayout,而 BoringLayout 则使用场景极为有限:当你确保你的文本只有一行,且所有的字符均是从左到右显示的(某些语言的文字是从右到左显示的),你才可以使用 BoringLayout。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">本文将会简单地深入 StaticLayout 的源码,分析下具体是如何工作的。</p><h2 style="line-height: inherit;margin-top: 1.6em;font-size: 18px;margin-bottom: 20px;color: rgb(92, 172, 238);text-align: center;"><span style="font-size: inherit;color: inherit;line-height: inherit;border-bottom: 1px solid rgb(92, 172, 238);padding-left: 5px;padding-right: 5px;padding-bottom: 3px;">概述</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">先看 StaticLayout 类的注释:StaticLayout 是一个为不可编辑的文本布局的类,这意味着一旦布局完成,文本内容就不可以改变,如果需要改变的话,应该使用 DynamicLayout 来布局。同时你不应该直接使用 StaticLayout 类,除非你需要实现一个自定义的控件或者自定义显示对象,否则,你应该直接调用 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Canvas.drawText()</code>。因此,在正常的开发工作中,你接触 StaticLayout 的机会应该不多。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">在 TextView 初始化时,会通过 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">makeNewLayout()</code> 方法,根据文本的特点,是否包含 Span,是否单行等,决定创建具体的 Layout 类型。在单纯地使用 TextView 来展示静态文本的时候,创建的就是 StaticLayout。StaticLayout 的初始化是通过内部类 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">StaticLayout.Builder</code> 完成的,然后调用 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">generate()</code> 方法完成段落、折行以及缩进之类的处理,在 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">generate()</code> 方法中调用了 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">out()</code>方法,完成文本显示的行距、顶部底部留白、省略文本等的处理,这两个方法也是 StaticLayout 源码中两个主要的方法,完成了一系列的文本处理。在 TextView 的 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">onDraw(Canvas canvas)</code> 方法中,调用父类 Layout 的 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">draw()</code> 方法,改方法会依次调用 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">drawBackground()</code> 和 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">drawText()</code> 完成背景和文本的绘制。</p><h2 style="line-height: inherit;margin-top: 1.6em;font-size: 18px;margin-bottom: 20px;color: rgb(92, 172, 238);text-align: center;"><span style="font-size: inherit;color: inherit;line-height: inherit;border-bottom: 1px solid rgb(92, 172, 238);padding-left: 5px;padding-right: 5px;padding-bottom: 3px;">构造方法</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">StaticLayout 有多个构造方法,最完整的构造方法(其他构造方法最终也是调用的这个构造方法)如下所示:</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">public</span> <span class="" style="font-size: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">StaticLayout</span><span class="" style="font-size: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">(CharSequence source, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> bufstart, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> bufend,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TextPaint paint, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> outerwidth,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Alignment align, TextDirectionHeuristic textDir,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">float</span> spacingmult, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">float</span> spacingadd,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">boolean</span> includepad,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TextUtils.TruncateAt ellipsize, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> ellipsizedWidth, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> maxLines)</span> </span>{<br> &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">super</span>((ellipsize == <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;? source<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: (source <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">instanceof</span> Spanned)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;? <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">new</span> SpannedEllipsizer(source)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">new</span> Ellipsizer(source),<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;paint, outerwidth, align, textDir, spacingmult, spacingadd);<br> &nbsp; &nbsp; &nbsp; &nbsp;Builder b = Builder.obtain(source, bufstart, bufend, paint, outerwidth)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setAlignment(align)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setTextDirection(textDir)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setLineSpacing(spacingadd, spacingmult)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setIncludePad(includepad)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setEllipsizedWidth(ellipsizedWidth)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setEllipsize(ellipsize)<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;.setMaxLines(maxLines);<br> &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (ellipsize != <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Ellipsizer e = (Ellipsizer) getText();<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;e.mLayout = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">this</span>;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;e.mWidth = ellipsizedWidth;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;e.mMethod = ellipsize;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mEllipsizedWidth = ellipsizedWidth;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mColumns = COLUMNS_ELLIPSIZE;<br> &nbsp; &nbsp; &nbsp; &nbsp;} <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">else</span> {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mColumns = COLUMNS_NORMAL;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mEllipsizedWidth = outerwidth;<br> &nbsp; &nbsp; &nbsp; &nbsp;}<br> &nbsp; &nbsp; &nbsp; &nbsp;mLineDirections = ArrayUtils.newUnpaddedArray(Directions.class, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span> * mColumns);<br> &nbsp; &nbsp; &nbsp; &nbsp;mLines = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">new</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[mLineDirections.length];<br> &nbsp; &nbsp; &nbsp; &nbsp;mMaximumVisibleLineCount = maxLines;<br> &nbsp; &nbsp; &nbsp; &nbsp;generate(b, b.mIncludePad, b.mIncludePad);<br> &nbsp; &nbsp; &nbsp; &nbsp;Builder.recycle(b);<br> &nbsp; &nbsp;}<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><strong style="font-size: inherit;color: inherit;line-height: inherit;">参数说明:</strong></p><ul style="" class="list-paddingleft-2"><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">CharSequence source</code> 文本内容。</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">int bufstart, int bufend,</code> 开始位置和结束位置。</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">TextPaint paint</code> 文本画笔对象。</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">int outerwidth</code> 布局宽度,超出宽度换行显示。</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">Alignment align</code> 对齐方式,默认是<code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">Alignment.ALIGN_LEFT</code>。</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">TextDirectionHeuristic textDir</code> 文本显示方向。</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">float spacingmult</code> 行间距倍数,默认是1。</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">float spacingadd</code> 行距增加值,默认是0。</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">boolean includepad</code> 文本顶部和底部是否留白。</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">TextUtils.TruncateAt ellipsize</code> 文本省略方式,有 START、MIDDLE、 END、MARQUEE 四种省略方式(其实还有一个 END_SMALL,但是 Google 并未开放出来)。</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">int ellipsizedWidth</code> 省略宽度。</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">int maxLines</code> 最大行数。</p></li></ul><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><strong style="font-size: inherit;color: inherit;line-height: inherit;">细节分析:</strong></p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">构造方法的开始,在调用父类 Layout 构造方法的时候,判断了文本是否需要省略,如果需要省略,则创建一个 Ellipsizer 对象,Ellipsizer 是 Layout 的嵌套内部类,实现了 CharSequence 和 GetChars 接口。该类就是用来对文本进行省略处理的,具体的处理方法是由其 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">getChars()</code> 方法完成的。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">在创建 Ellipsizer 对象之前,还判断了一下需要显示的文本是否是 Spanned ,如果是的话则创建 SpannedEllipsizer 对象,SpannedEllipsizer 类继承 Ellipsizer,同时实现了 Spanned 接口。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">StaticLayout.Builder 对象的创建是通过 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Builder.obtain()</code> 方法创建的,在该方法内部可以看到 Builder 对象通过 SynchronizedPool 对象池来管理的,起到缓存的作用,避免 Builder 对象的重复创建,在 StaticLayout 的构造方法的最后也可以看到 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Builder.recycle(b)</code> 的调用,回收 Builder 对象。 Builder 的构造方法如下所示:</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">private</span> <span class="" style="font-size: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">Builder</span><span class="" style="font-size: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">()</span> </span>{<br> &nbsp; mNativePtr = nNewBuilder();<br>}<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">其调用了 JNI 层的 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">nNewBuilder()</code> 方法,新建了一个 LineBreak 对象,并将其指针指向 Java 层,赋值给 Builder 对象的 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">mNativePtr</code> 字段 ,后面调用 native 方法时,均需要将 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">mNativePtr</code> 作为参数传递过去。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"> <span class="" style="font-size: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">static</span> jlong <span class="" style="font-size: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">nNewBuilder</span><span class="" style="font-size: inherit;line-height: inherit;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">(JNIEnv*, jclass)</span> </span>{<br> &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">return</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">reinterpret_cast</span>&lt;jlong&gt;(<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">new</span> LineBreaker);<br> }<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">mLineDirections</code> 需要结合到后面每行文本处理来理解,这里可以大致说一下,StaticLayout 源码中声明了以下的常量:</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> COLUMNS_NORMAL = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span>;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> COLUMNS_ELLIPSIZE = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">6</span>;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> START = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> DIR = START;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> TAB = START;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> TOP = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> DESCENT = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span>;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> HYPHEN = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">3</span>;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> ELLIPSIS_START = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span>;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> ELLIPSIS_COUNT = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">5</span>;<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">其中 COLUMNS_NORMAL 和 COLUMNS_ELLIPSIZE 会赋值给全局变量 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">mColumns</code>,正如你在构造方法中看到的那样,这个在没一行处理时会用到,每一行文本处理时需要记录四个值,start,top,desent,hyphen 值,当文本需要被省略时,还需要记录 ellipsis_start 和 ellipsis_count 值,因此正常的 mColumn 值为4,省略时则是 6,因此 mLineDirections 数组大小始终是 mColumn 的倍数,mLine 数组的大小和其保持一致(从后面的分析来看,mLineDirections 数组的大小没必要这么大)。</p><h2 style="line-height: inherit;margin-top: 1.6em;font-size: 18px;margin-bottom: 20px;color: rgb(92, 172, 238);text-align: center;"><span style="font-size: inherit;color: inherit;line-height: inherit;border-bottom: 1px solid rgb(92, 172, 238);padding-left: 5px;padding-right: 5px;padding-bottom: 3px;">generate 方法分析</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">StaticLayout 中的 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">generate()</code> 方法近 300 行,其完成了文本的段落、折行的处理,建议自行对照源码来阅读下面的分析,本文不贴太多代码。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><strong style="font-size: inherit;color: inherit;line-height: inherit;">接受的参数:</strong></p><ul style="" class="list-paddingleft-2"><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">StaticLayout.Builder b</code>&nbsp; StaticLayout.Builder 对象</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">boolean includepad</code>是否上下保留空白</p></li><li><p><code style="line-height: inherit;padding-right: 0.5em;padding-left: 0.5em;border-radius: 3px;background-color: rgb(249, 242, 244);border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;">boolean trackpad</code></p></li></ul><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><strong style="font-size: inherit;color: inherit;line-height: inherit;">细节分析:</strong></p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">1、在方法的开始,创建了很多的局部变量,并将 Builder 对象对应的值赋值给这些变量。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">其中有个 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">Paint.FontMetricsInt fm</code> 变量,FontMetricsInt 是 Paint 的内部类,主要用来完成字体测量,其和 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">FontMetrics</code>非常类似,只是在文字测量时,对应的数值均是 int 类型,FontMetrics 是 float 类型。FontMetricsInt 类主要包含保存了字体测量相关的数据。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><strong style="font-size: inherit;color: inherit;line-height: inherit;">源码如下:</strong></p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">public</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">static</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">class</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(220, 220, 220);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">FontMetricsInt</span> {</span><br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">public</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> &nbsp; top;<br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">public</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> &nbsp; ascent;<br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">public</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> &nbsp; descent;<br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">public</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> &nbsp; bottom;<br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">public</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> &nbsp; leading;<br>}<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">每个值的含义如下图所示,在 baseline 之上为负值,baseline 之下为正值,leading 表示两行文本 baseline 之间的距离,这个值可以由行间距倍数和行间距增加值来调整。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><img class="img_loading" data-ratio="0.4646791963707064" data-src="https://mmbiz.qpic.cn/mmbiz_jpg/liaczD18OicSxPzCbnGx22LHt2MWlU1Az6BeTibewqUicfiaWvLdhSiaWQcrwI2qick8hIl7vuQoUQJF8emo9pnF66BIw/640" data-type="jpeg" data-w="1543" style="font-size: inherit; color: inherit; line-height: inherit; display: block; margin-right: auto; margin-left: auto; border-style: none; border-radius: 0px; width: 664px !important; height: 308.547px !important;" src="https://img-blog.csdnimg.cn/2022010616151418405.gif"></p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">在接下来的字体测量中,会使用 fmCache 数组来缓存字体测量的信息,缓存 top, bottom, ascent 和 descen 四个值,因此 fmCache 数组的大小始终是 4 的倍数。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">2、接下来就是按照一个个段落来处理文本。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">for</span> (int paraStart = bufStart; paraStart &lt;= bufEnd; paraStart = paraEnd) {<br> &nbsp; &nbsp;paraEnd = TextUtils.indexOf(<span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">source</span>, CHAR_NEW_LINE, paraStart, bufEnd);<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (paraEnd &lt; 0)<br> &nbsp; &nbsp; &nbsp; &nbsp;paraEnd = bufEnd;<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">else</span><br> &nbsp; &nbsp; &nbsp; &nbsp;paraEnd++;<br> &nbsp; &nbsp;...<br>}<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">通过查找换行符,确定每个段落的起止位置,接下来的处理,均是对该段落文本的处理。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">3、span 文本的处理。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">4、处理段落文本。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;">measured.setPara(source, paraStart, paraEnd, textDir, b);<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">char</span>[] chs = measured.mChars;<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">float</span>[] widths = measured.mWidths;<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">byte</span>[] chdirs = measured.mLevels;<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> dir = measured.mDir;<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">boolean</span> easy = measured.mEasy;<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">5、处理制表位,这里的制表位是使用 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">TabStopSpan</code> 方式插入到文本中的,通过 Spanned 接口提供的 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">getSpans(int start, int end, Class type)</code> 方法来获取到 TabStopSpan,排序后将所有的制表位的位置存在 variableTabStops 数组中。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[] variableTabStops = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>;<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (spanned != <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>) {<br> &nbsp; &nbsp;TabStopSpan[] spans = getParagraphSpans(spanned, paraStart,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;paraEnd, TabStopSpan.class);<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (spans.length &gt; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>) {<br> &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[] stops = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">new</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[spans.length];<br> &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">for</span> (<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> i = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>; i &lt; spans.length; i++) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;stops[i] = spans[i].getTabStop();<br> &nbsp; &nbsp; &nbsp; &nbsp;}<br> &nbsp; &nbsp; &nbsp; &nbsp;Arrays.sort(stops, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, stops.length);<br> &nbsp; &nbsp; &nbsp; &nbsp;variableTabStops = stops;<br>}}<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">6、完成以上处理后,就是交给 JNI 层来处理段落文本,主要处理了段落的制表行缩进、折行等,需要再分析。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">nSetupParagraph</span>(<span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">b</span><span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">.mNativePtr</span>, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">chs</span>, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">paraEnd</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">-</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">paraStart</span>,<br> &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">firstWidth</span>, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">firstWidthLineCount</span>, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">restWidth</span>,<br> &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">variableTabStops</span>, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">TAB_INCREMENT</span>, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">b</span><span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">.mBreakStrategy</span>, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">b</span><span class="" style="font-size: inherit;line-height: inherit;color: rgb(215, 186, 125);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">.mHyphenationFrequency</span>);<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">7、处理缩进的源码如下。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (mLeftIndents != <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span> || mRightIndents != <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>) {<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> leftLen = mLeftIndents == <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span> ? <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> : mLeftIndents.length;<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> rightLen = mRightIndents == <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span> ? <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> : mRightIndents.length;<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> indentsLen = Math.max(<span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>, Math.min(leftLen, rightLen) - mLineCount);<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[] indents = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">new</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[indentsLen];<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">for</span> (<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> i = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>; i &lt; indentsLen; i++) {<br> &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> leftMargin = mLeftIndents == <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span> ? <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> :<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mLeftIndents[Math.min(i + mLineCount, leftLen - <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>)];<br> &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> rightMargin = mRightIndents == <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span> ? <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> :<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mRightIndents[Math.min(i + mLineCount, rightLen - <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>)];<br> &nbsp; &nbsp; &nbsp; &nbsp;indents[i] = leftMargin + rightMargin;<br> &nbsp; &nbsp;}<br> &nbsp; &nbsp;nSetIndents(b.mNativePtr, indents);<br>}<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">开始的条件判断使用的 mLeftIndents 和 mRightIndents 变量是通过 Builder 对象来赋值的。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(156, 220, 254);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">mLeftIndents</span> = b.mLeftIndents;<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(156, 220, 254);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">mRightIndents</span> = b.mRightIndents;<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">但是比较困惑的是,源码中并没有对 Builder 对象这两个字段赋值的地方,因此这里的条件判断结果都是 false,实际 debug 测试了下,这个地方的判断确实始终是 false,所以具体的逻辑还需要再分析下。可以看见的是,在方法的最后,同样是调用 JNI 层的方法设置缩进。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">8、缓存字体测量信息,源码如下。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">for</span> (<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> spanStart = paraStart, spanEnd; spanStart &lt; paraEnd; spanStart = spanEnd) {<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (fmCacheCount * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span> &gt;= fmCache.length) {<br> &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[] grow = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">new</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[fmCacheCount * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span> * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span>];<br> &nbsp; &nbsp; &nbsp; &nbsp;System.arraycopy(fmCache, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, grow, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, fmCacheCount * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span>);<br> &nbsp; &nbsp; &nbsp; &nbsp;fmCache = grow;<br> &nbsp; &nbsp;}<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (spanEndCacheCount &gt;= spanEndCache.length) {<br> &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[] grow = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">new</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[spanEndCacheCount * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span>];<br> &nbsp; &nbsp; &nbsp; &nbsp;System.arraycopy(spanEndCache, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, grow, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, spanEndCacheCount);<br> &nbsp; &nbsp; &nbsp; &nbsp;spanEndCache = grow;<br> &nbsp; &nbsp;}<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (spanned == <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>) {<br> &nbsp; &nbsp; &nbsp; &nbsp;spanEnd = paraEnd;<br> &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> spanLen = spanEnd - spanStart;<br> &nbsp; &nbsp; &nbsp; &nbsp;measured.addStyleRun(paint, spanLen, fm);<br> &nbsp; &nbsp;} <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">else</span> {<br> &nbsp; &nbsp; &nbsp; &nbsp;spanEnd = spanned.nextSpanTransition(spanStart, paraEnd,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MetricAffectingSpan.class);<br> &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> spanLen = spanEnd - spanStart;<br> &nbsp; &nbsp; &nbsp; &nbsp;MetricAffectingSpan[] spans =<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;spanned.getSpans(spanStart, spanEnd, MetricAffectingSpan.class);<br> &nbsp; &nbsp; &nbsp; &nbsp;spans = TextUtils.removeEmptySpans(spans, spanned, MetricAffectingSpan.class);<br> &nbsp; &nbsp; &nbsp; &nbsp;measured.addStyleRun(paint, spans, spanLen, fm);<br> &nbsp; &nbsp;}<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// the order of storage here (top, bottom, ascent, descent) has to match the code below</span><br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// where these values are retrieved</span><br> &nbsp; &nbsp;fmCache[fmCacheCount * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span> + <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>] = fm.top;<br> &nbsp; &nbsp;fmCache[fmCacheCount * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span> + <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>] = fm.bottom;<br> &nbsp; &nbsp;fmCache[fmCacheCount * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span> + <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span>] = fm.ascent;<br> &nbsp; &nbsp;fmCache[fmCacheCount * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span> + <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">3</span>] = fm.descent;<br> &nbsp; &nbsp;fmCacheCount++;<br> &nbsp; &nbsp;spanEndCache[spanEndCacheCount] = spanEnd;<br> &nbsp; &nbsp;spanEndCacheCount++;<br>}<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">fmCache 的初始化时的大小是 16,因此在每次循环开始时,需要判断下是否需要对 fmCache 扩容,这里的扩容同样保证了 fmCache 的大小是 4 的倍数,同时每次扩容时都是双倍扩容。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">这里也会对文本中的 Span 的结束位置使用 spanEndCache 缓存记录下来,这里处理的 span 具体类型是 MetricAffectingSpan,顾名思义就是对字体会有影响的 Span,需要单独拿出来处理,缓存字体测量信息。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">具体的测量则是交给 MeasuredText 类的 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">addStyleRun(TextPaint paint, int len, Paint.FontMetricsInt fm)</code> 和 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">addStyleRun(TextPaint paint, MetricAffectingSpan[] spans, int len, Paint.FontMetricsInt fm)</code> 方法来处理,具体的处理涉及到文字的排版,感兴趣的可以自己查看源码,这里不再详细分析了。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">测量完成后,字体测量信息的值4个一组地存储在 fmCache 数组中,spanEnd 值存储在 spanEndCache 数组中。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">9、计算每行宽度和折行处理,宽度的计算和折行的处理分别借助 JNI 层的 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">nGetWidths()</code> 和 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">nComputeLineBreaks()</code> 方法来处理。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"> nGetWidths(b.mNativePtr, widths);<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 得到当前行内包含的折行数目</span><br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> breakCount = nComputeLineBreaks(b.mNativePtr, lineBreaks, lineBreaks.breaks,<br> &nbsp; &nbsp; &nbsp; &nbsp; lineBreaks.widths, lineBreaks.flags, lineBreaks.breaks.length);<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[] breaks = lineBreaks.breaks;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">float</span>[] lineWidths = lineBreaks.widths;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[] flags = lineBreaks.flags;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 得到剩下的行数 = 最大允许行数 - 当前行数</span><br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">final</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> remainingLineCount = mMaximumVisibleLineCount - mLineCount;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">final</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">boolean</span> ellipsisMayBeApplied = ellipsize != <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span><br> &nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; (ellipsize == TextUtils.TruncateAt.END<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; || (mMaximumVisibleLineCount == <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span><br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;&amp; ellipsize != TextUtils.TruncateAt.MARQUEE));<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 如果剩下的行数小于当前行包含的折行数目,则需要将最后一行和超出的行处理成单行</span><br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (remainingLineCount &gt; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span> &amp;&amp; remainingLineCount &lt; breakCount &amp;&amp;<br> &nbsp; &nbsp; &nbsp; &nbsp; ellipsisMayBeApplied) {<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// Treat the last line and overflowed lines as a single line.</span><br> &nbsp; &nbsp; breaks[remainingLineCount - <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>] = breaks[breakCount - <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>];<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 计算 width 和 flag 值</span><br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">float</span> width = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>;<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> flag = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>;<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">for</span> (<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> i = remainingLineCount - <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>; i &lt; breakCount; i++) {<br> &nbsp; &nbsp; &nbsp; &nbsp; width += lineWidths[i];<br> &nbsp; &nbsp; &nbsp; &nbsp; flag |= flags[i] &amp; TAB_MASK;<br> &nbsp; &nbsp; }<br> &nbsp; &nbsp; lineWidths[remainingLineCount - <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>] = width;<br> &nbsp; &nbsp; flags[remainingLineCount - <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>] = flag;<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 设置当前行中的折行数为可用的行数</span><br> &nbsp; &nbsp; breakCount = remainingLineCount;<br> }<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">处理完折行后,会判断下是否需要省略处理,如果需要,则根据允许的最大行数和当前行包含的折行数目来确定需要处理成省略的那一行,并设置相关的 width 和 flag 信息。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">10、处理文本中 Span 和折行。源码如下:</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> here = paraStart;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> fmTop = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, fmBottom = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, fmAscent = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, fmDescent = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> fmCacheIndex = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> spanEndCacheIndex = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> breakIndex = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">for</span> (<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> spanStart = paraStart, spanEnd; spanStart &lt; paraEnd; spanStart = spanEnd) {<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 从之前存储的数据中获取 span 结束位置</span><br> &nbsp; &nbsp; spanEnd = spanEndCache[spanEndCacheIndex++];<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 恢复之前存储的字体测量信息</span><br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// retrieve cached metrics, order matches above</span><br> &nbsp; &nbsp; fm.top = fmCache[fmCacheIndex * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span> + <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>];<br> &nbsp; &nbsp; fm.bottom = fmCache[fmCacheIndex * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span> + <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>];<br> &nbsp; &nbsp; fm.ascent = fmCache[fmCacheIndex * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span> + <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">2</span>];<br> &nbsp; &nbsp; fm.descent = fmCache[fmCacheIndex * <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">4</span> + <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">3</span>];<br> &nbsp; &nbsp; fmCacheIndex++;<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 参照前面提到的字体测量的几个值的说明,这里的 top 和 ascent 取值小的,bottom 和 descent 取值大的,保证文本均可以正常显示</span><br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (fm.top &lt; fmTop) {<br> &nbsp; &nbsp; &nbsp; &nbsp; fmTop = fm.top;<br> &nbsp; &nbsp; }<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (fm.ascent &lt; fmAscent) {<br> &nbsp; &nbsp; &nbsp; &nbsp; fmAscent = fm.ascent;<br> &nbsp; &nbsp; }<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (fm.descent &gt; fmDescent) {<br> &nbsp; &nbsp; &nbsp; &nbsp; fmDescent = fm.descent;<br> &nbsp; &nbsp; }<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (fm.bottom &gt; fmBottom) {<br> &nbsp; &nbsp; &nbsp; &nbsp; fmBottom = fm.bottom;<br> &nbsp; &nbsp; }<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 跳过 span 之前的折行</span><br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">while</span> (breakIndex &lt; breakCount &amp;&amp; paraStart + breaks[breakIndex] &lt; spanStart) {<br> &nbsp; &nbsp; &nbsp; &nbsp; breakIndex++;<br> &nbsp; &nbsp; }<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 处理 span 中的折行</span><br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">while</span> (breakIndex &lt; breakCount &amp;&amp; paraStart + breaks[breakIndex] &lt;= spanEnd) {<br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> endPos = paraStart + breaks[breakIndex];<br> &nbsp; &nbsp; &nbsp; &nbsp; boolean moreChars = (endPos &lt; bufEnd);<br> &nbsp; &nbsp; &nbsp; &nbsp; v = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">out</span>(source, here, endPos,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmAscent, fmDescent, fmTop, fmBottom,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; v, spacingmult, spacingadd, chooseHt,chooseHtv, fm, flags[breakIndex],<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chs, widths, paraStart, ellipsize, ellipsizedWidth,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lineWidths[breakIndex], paint, moreChars);<br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (endPos &lt; spanEnd) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 如果 Span 文本还未处理完成,则恢复当前的 fontMetrics 信息</span><br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 否则归零处理,处理下一段 Span</span><br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// preserve metrics for current span</span><br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmTop = fm.top;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmBottom = fm.bottom;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmAscent = fm.ascent;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmDescent = fm.descent;<br> &nbsp; &nbsp; &nbsp; &nbsp; } <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">else</span> {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmTop = fmBottom = fmAscent = fmDescent = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>;<br> &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; &nbsp; &nbsp; here = endPos;<br> &nbsp; &nbsp; &nbsp; &nbsp; breakIndex++;<br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 如果处理该段落时行数已经超过最大可见行数,则直接终止后面的处理</span><br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (mLineCount &gt;= mMaximumVisibleLineCount) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">return</span>;<br> &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; }<br> }<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 如果段落结束就是整个文本的结束,则跳出处理段落的循环,否则处理下一段。</span><br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (paraEnd == bufEnd)<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">break</span>;<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">至此,以段落为单位的文本就处理完毕,包括文本的折行、Span 的处理都已完成。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">11、当需要处理的文本起止位置相同时(即需要处理的文本为空),且前面是换行符时,此时也需要将该空白处理成一个段落。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">代码如下:</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"> &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> ((bufEnd == bufStart || source.charAt(bufEnd - <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>) == CHAR_NEW_LINE) &amp;&amp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mLineCount &lt; mMaximumVisibleLineCount) {<br> &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> Log.e(<span class="" style="font-size: inherit;line-height: inherit;color: rgb(214, 157, 133);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">"text"</span>, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(214, 157, 133);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">"output last "</span> + bufEnd);<br> &nbsp; &nbsp; &nbsp;measured.setPara(source, bufEnd, bufEnd, textDir, b);<br> &nbsp; &nbsp; &nbsp;paint.getFontMetricsInt(fm);<br> &nbsp; &nbsp; &nbsp;v = out(source,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bufEnd, bufEnd, fm.ascent, fm.descent,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fm.top, fm.bottom,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;v,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;spacingmult, spacingadd, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>, fm, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;needMultiply, measured.mLevels, measured.mDir, measured.mEasy, bufEnd,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;includepad, trackpad, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>, bufStart, ellipsize,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ellipsizedWidth, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, paint, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">false</span>);<br> &nbsp;}<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">第10点和第11点分析中均出现了 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">out()</code> 方法,前面提到,该方法也是 StaticLayout 源码中的一个重要的方法,接下来会分析下 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">out</code> 方法中做了什么处理。</p><h2 style="line-height: inherit;margin-top: 1.6em;font-size: 18px;margin-bottom: 20px;color: rgb(92, 172, 238);text-align: center;"><span style="font-size: inherit;color: inherit;line-height: inherit;border-bottom: 1px solid rgb(92, 172, 238);padding-left: 5px;padding-right: 5px;padding-bottom: 3px;">out 方法分析</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">out()</code> 方法在我看来,就是 layout 中的 out。如果说 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">generate()</code> 大部分是处理一些折行、段落相关的数据,那么 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">out()</code> 方法就是将这些数据使用起来,真正地布局出来(注意,布局不是显示,显示的话还是在父类的 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">drawText()</code> 方法中进行的)。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">1、方法接收的参数如下所示,很多参数都是在 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">generate()</code> 中处理获得,参数的含义和前面提到的基本相同。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;">out(CharSequence text, int <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">start</span>, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">end</span>,<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> above, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> below, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> top, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> bottom, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> v,<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">float</span> spacingmult, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">float</span> spacingadd,<br> &nbsp; &nbsp;LineHeightSpan[] chooseHt, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[] chooseHtv,<br> &nbsp; &nbsp;Paint.FontMetricsInt fm, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> flags,<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">boolean</span> needMultiply, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">byte</span>[] chdirs, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> dir,<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">boolean</span> easy, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> bufEnd, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">boolean</span> includePad,<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">boolean</span> trackPad, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">char</span>[] chs,<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">float</span>[] widths, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> widthStart, TextUtils.TruncateAt ellipsize,<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">float</span> ellipsisWidth, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">float</span> textWidth,<br> &nbsp; &nbsp;TextPaint paint, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(78, 201, 176);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">boolean</span> moreChars) <br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">2、对 mLineDirections 和 mLine 扩容处理,根据当前行数,判断下 mLine 数组大小是否足够储存当前行的信息,如果不够,则扩容,对应的 mLineDirections 也进行扩容处理(两个数组大小相同)。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> j = mLineCount;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> off = j * mColumns;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> want = off + mColumns + TOP;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[] lines = mLines;<br> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (want &gt;= lines.length) {<br> &nbsp; &nbsp; Directions[] grow2 = ArrayUtils.newUnpaddedArray(<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Directions.class, GrowingArrayUtils.growSize(want))<br> &nbsp; &nbsp; System.arraycopy(mLineDirections, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, grow2, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;mLineDirections.length);<br> &nbsp; &nbsp; mLineDirections = grow2;<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[] grow = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">new</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>[grow2.length];<br> &nbsp; &nbsp; System.arraycopy(lines, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, grow, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>, lines.length);<br> &nbsp; &nbsp; mLines = grow;<br> &nbsp; &nbsp; lines = grow;<br> }<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">3、待分析。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (chooseHt != <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>) {<br> &nbsp; &nbsp; fm.ascent = above;<br> &nbsp; &nbsp; fm.descent = below;<br> &nbsp; &nbsp; fm.top = top;<br> &nbsp; &nbsp; fm.bottom = bottom;<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">for</span> (<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> i = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>; i &lt; chooseHt.length; i++) {<br> &nbsp; &nbsp; &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (chooseHt[i] <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">instanceof</span> LineHeightSpan.WithDensity) {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ((LineHeightSpan.WithDensity) chooseHt[i]).<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chooseHeight(text, start, end, chooseHtv[i], v, fm, paint);<br> &nbsp; &nbsp; &nbsp; &nbsp; } <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">else</span> {<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; chooseHt[i].chooseHeight(text, start, end, chooseHtv[i], v, fm);<br> &nbsp; &nbsp; &nbsp; &nbsp; }<br> &nbsp; &nbsp; }<br> &nbsp; &nbsp; above = fm.ascent;<br> &nbsp; &nbsp; below = fm.descent;<br> &nbsp; &nbsp; top = fm.top;<br> &nbsp; &nbsp; bottom = fm.bottom;<br> } &nbsp; &nbsp;<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">4、第一行和最后一行的特殊处理,以及行间距的处理</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 判断是否是第一行</span><br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">boolean</span> firstLine = (j == <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>);<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 判断是否是最后一行:全部文本的最后一行或者行数等于可见的最大的行数</span><br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">boolean</span> currentLineIsTheLastVisibleOne = (j + <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span> == mMaximumVisibleLineCount);<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">boolean</span> lastLine = currentLineIsTheLastVisibleOne || (end == bufEnd);<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 第一行需要处理上面的留白</span><br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (firstLine) {<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (trackPad) {<br> &nbsp; &nbsp; &nbsp; &nbsp; mTopPadding = top - above;<br> &nbsp; &nbsp; }<br> &nbsp; &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (includePad) {<br> &nbsp; &nbsp; &nbsp; &nbsp; above = top;<br> &nbsp; &nbsp; }<br>}<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span> extra;<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 最后一行需要处理下面的留白</span><br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (lastLine) {<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (trackPad) {<br> &nbsp; &nbsp; &nbsp; &nbsp;mBottomPadding = bottom - below;<br> &nbsp; &nbsp;}<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (includePad) {<br> &nbsp; &nbsp; &nbsp; &nbsp;below = bottom;<br> &nbsp; &nbsp;}<br>}<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(87, 166, 74);font-style: italic;word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">// 处理行间距</span><br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (needMultiply &amp;&amp; !lastLine) {<br> &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">double</span> ex = (below - above) * (spacingmult - <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span>) + spacingadd;<br> &nbsp; <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (ex &gt;= <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>) {<br> &nbsp; &nbsp; &nbsp; extra = (<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>)(ex + EXTRA_ROUNDING);<br> &nbsp; } <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">else</span> {<br> &nbsp; &nbsp; &nbsp; extra = -(<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">int</span>)(-ex + EXTRA_ROUNDING);<br> &nbsp; }<br>} <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">else</span> {<br> &nbsp; extra = <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">0</span>;<br>}<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">5、接下来就是记录每行的文本的信息,需要注意到的是,每行的信息由 lines 中的连续的值来记录,值的数量等于 mColumns 的大小( mColumns 的取值前面有提到)。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> 记录每行的起止位置,顶部和底部位置<br>lines[<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">off</span> + START] = start;<br>lines[<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">off</span> + TOP] = v;<br>lines[<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">off</span> + DESCENT] = below + extra;<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> 记录下一行的起始位置和顶部位置,v 值会作为返回值返回给调用的地方。<br>v += (below - above) + extra;<br>lines[<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">off</span> + mColumns + START] = end;<br>lines[<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">off</span> + mColumns + TOP] = v;<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> TODO: could move TAB to share same column <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">as</span> HYPHEN, simplifying <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">this</span> code <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">and</span> gaining<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> one bit <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">for</span> start field<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> 通过位运算记录 tab 和文本方向信息<br>lines[<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">off</span> + TAB] |= flags &amp; TAB_MASK;<br>lines[<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">off</span> + HYPHEN] = flags;<br>lines[<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">off</span> + DIR] |= dir &lt;&lt; DIR_SHIFT;<br>Directions linedirs = DIRS_ALL_LEFT_TO_RIGHT;<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> easy means all chars &lt; the first RTL, so <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">no</span> emoji, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">no</span> nothing<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> XXX a run with <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">no</span> text <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">or</span> all spaces <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">is</span> easy but might be an empty<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> RTL paragraph. &nbsp;Make sure easy <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">is</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">false</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">this</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">is</span> the case.<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> 记录文本的方向<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (easy) {<br> &nbsp; &nbsp;mLineDirections[j] = linedirs;<br>} <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">else</span> {<br> &nbsp; &nbsp;mLineDirections[j] = AndroidBidi.directions(dir, chdirs, start - widthStart, chs,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;start - widthStart, end - start);<br>}<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">6、文本省略的处理。</p><pre style="line-height: inherit;margin: 0px;padding: 0px;border-radius: 3px;background-color: rgb(249, 242, 244);font-size: 0.9em;letter-spacing: normal;color: rgb(199, 37, 78);margin-left: 0.2em;margin-right: 0.2em;"><code class="" style="border-radius: 3px;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);margin-left: 0.2em;margin-right: 0.2em;font-family: Consolas, Inconsolata, Courier, monospace;line-height: 18px;font-size: 14px;word-spacing: 0px;letter-spacing: 0px;padding: 0.5em;background: rgb(30, 30, 30);color: rgb(220, 220, 220);display: block !important;word-wrap: normal !important;overflow: auto !important;"><span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> 判读是否需要省略<br><span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (ellipsize != <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">null</span>) {<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> If there <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">is</span> only one line, <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">then</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">do</span> any type <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">of</span> ellipsis except <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">when</span> it <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">is</span> MARQUEE<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(154, 83, 52);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">//</span> <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> there are multiple lines, just allow END ellipsis <span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">on</span> the last line<br> &nbsp; &nbsp;boolean forceEllipsis = moreChars &amp;&amp; (mLineCount + <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span> == mMaximumVisibleLineCount);<br> &nbsp; &nbsp;boolean doEllipsis =<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(((mMaximumVisibleLineCount == <span class="" style="font-size: inherit;line-height: inherit;color: rgb(184, 215, 163);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">1</span> &amp;&amp; moreChars) || (firstLine &amp;&amp; !moreChars)) &amp;&amp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ellipsize != TextUtils.TruncateAt.MARQUEE) ||<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(!firstLine &amp;&amp; (currentLineIsTheLastVisibleOne || !moreChars) &amp;&amp;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ellipsize == TextUtils.TruncateAt.END);<br> &nbsp; &nbsp;<span class="" style="font-size: inherit;line-height: inherit;color: rgb(86, 156, 214);word-wrap: inherit !important;word-break: inherit !important;white-space: inherit !important;">if</span> (doEllipsis) {<br> &nbsp; &nbsp; &nbsp; &nbsp;calculateEllipsis(start, end, widths, widthStart,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ellipsisWidth, ellipsize, j,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;textWidth, paint, forceEllipsis);<br> &nbsp; &nbsp;}<br>}<br></code></pre><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">如 Google 的工程师注释所说的那样,如果是指定了最大行数是 1,则任何省略方式都可以,如果指定的最大行数不是 1,但是只有单行文本时,除了 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">MARQUEE</code> 的省略方式不支持以外,其他的省略方式都是支持的。如果是多行省略,且不止一行文本时,只支持在可见的最后一行的最后省略,即 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">END</code> 省略方式。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">省略的计算是通过 <code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">calculateEllipsis()</code> 方法实现的,其内部处理完成会将省略的起始位置和计数复制给 mLines 对应的每行数据的第5和第6个数据(省略时每行的记录的数据个数为6个,即 mColumns 赋的值是 COLUMNS_ELLIPSIZE 的值,即6) ,<code style="line-height: inherit;border-width: 1px;border-style: solid;border-color: rgb(204, 204, 204);font-size: 0.9em;letter-spacing: normal;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;color: rgb(233, 105, 0);background: rgb(248, 248, 248);">calculateEllipsis()</code>方法的实现这里就不作具体分析了。</p><h2 style="line-height: inherit;margin-top: 1.6em;font-size: 18px;margin-bottom: 20px;color: rgb(92, 172, 238);text-align: center;"><span style="font-size: inherit;color: inherit;line-height: inherit;border-bottom: 1px solid rgb(92, 172, 238);padding-left: 5px;padding-right: 5px;padding-bottom: 3px;">总结</span></h2><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">至此,StaticLayout 的源码大致分析了一遍,后面需要结合 TextView 和 Layout 来具体看一下,文字到底是怎么绘制到屏幕上的。</p><blockquote style="font-size: inherit;line-height: inherit;color: rgb(102, 102, 102);border-top: 1px solid rgb(221, 221, 221);border-right: 1px solid rgb(221, 221, 221);border-bottom: 1px solid rgb(221, 221, 221);border-left-color: rgb(92, 172, 238);background-color: rgb(255, 255, 255);border-radius: 2px;padding-left: 20px;padding-right: 20px;margin-top: 0.8em;margin-bottom: 0.8em;"><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">今天在<strong style="font-size: inherit;color: inherit;line-height: inherit;">承香墨影</strong>公众号的后台,回复『<strong style="font-size: inherit;color: inherit;line-height: inherit;">成长</strong>』。我会送你一些我整理的学习资料。</p><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;">我另外还维护了一个技术交流的微信群,有兴趣可以在公众号后台回复:"加群"</p></blockquote><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><span style="color: inherit;font-size: inherit;">推荐阅读:</span><br></p><ul style="" class="list-paddingleft-2"><li><p><a href="http://mp.weixin.qq.com/s?__biz=MzIxNjc0ODExMA==&amp;mid=2247485033&amp;idx=1&amp;sn=54dd477b4c4cd30d12fde48eba929546&amp;chksm=97851f48a0f2965e342a2cdf55cbefceaa20a24b887e2b79ff940ca57a17b6cb9ae999643ace&amp;scene=21#wechat_redirect" style="line-height: inherit;color: rgb(30, 107, 184);text-align: left;font-size: 12px;text-decoration: underline;"><span style="font-size: 12px;">站在Android开发的角度,聊聊Airbnb的Lottie</span></a></p></li><li><p><a href="http://mp.weixin.qq.com/s?__biz=MzIxNjc0ODExMA==&amp;mid=2247485069&amp;idx=1&amp;sn=69a960d716f3948928b1381179b8744d&amp;chksm=97851faca0f296ba4ed5c2af8da17dc0726dc08961bee2f5652f7f0b070c23f158727d3e9874&amp;scene=21#wechat_redirect" style="line-height: inherit;color: rgb(30, 107, 184);text-align: left;font-size: 12px;text-decoration: underline;"><span style="font-size: 12px;">这些工具,让你写博客的时候,只需要专注写作!</span></a></p></li><li><p><a href="http://mp.weixin.qq.com/s?__biz=MzIxNjc0ODExMA==&amp;mid=2247485045&amp;idx=1&amp;sn=6293de722b4bde5e48627217ae11b0b3&amp;chksm=97851f54a0f296429f2083d742af5cee5ff852f02d6b13c34c0ceefeed83c24f66eae8f73686&amp;scene=21#wechat_redirect" style="line-height: inherit;color: rgb(30, 107, 184);text-align: left;font-size: 12px;text-decoration: underline;"><span style="font-size: 12px;">找了一天找不到 Bug ? 试试 Git 的二分法吧!!!</span></a></p></li><li><p><a href="http://mp.weixin.qq.com/s?__biz=MzIxNjc0ODExMA==&amp;mid=2247485013&amp;idx=1&amp;sn=725eb646e821ee16387a25d35b1b868b&amp;chksm=97851f74a0f29662c39cf5ce49a6ef5adce41583e4a48afcda7632a445ed7ac9bb6b3d7426dc&amp;scene=21#wechat_redirect" style="line-height: inherit;color: rgb(30, 107, 184);text-align: left;font-size: 12px;text-decoration: underline;"><span style="font-size: 12px;">如何更精准的在 Github 上搜索开源库?你需要这些技巧!</span></a></p></li><li><p><a href="http://mp.weixin.qq.com/s?__biz=MzIxNjc0ODExMA==&amp;mid=2247485072&amp;idx=1&amp;sn=e1acf7aad9cc66fddadec62cb3eafb62&amp;chksm=97851fb1a0f296a75bcaa87442f254304a49239dd64bc93fcdfe6974f1cf11d15c403aa5ed26&amp;scene=21#wechat_redirect" style="line-height: inherit;color: rgb(30, 107, 184);text-align: left;font-size: 12px;text-decoration: underline;"><span style="font-size: 12px;">Android开发,遇上 Emoji 头疼吗?</span></a></p></li></ul><p style="font-size: inherit;color: inherit;line-height: inherit;margin-top: 1.5em;margin-bottom: 1.5em;"><img class="img_loading" data-ratio="1" data-src="https://mmbiz.qpic.cn/mmbiz_jpg/liaczD18OicSxPzCbnGx22LHt2MWlU1Az6622Kg5DZrExoia3tV1nVm7cVC2iaSoOuGJF8pM8KhdB2AdOtOVfbcOWQ/640" data-type="jpeg" data-w="600" style="font-size: inherit; color: inherit; line-height: inherit; display: block; margin-right: auto; margin-left: auto; border-style: none; border-radius: 0px; width: 600px !important; height: 600px !important;" src="https://img-blog.csdnimg.cn/2022010616151418405.gif"></p></section>

转自:https://mp.weixin.qq.com/s?__biz=MzIxNjc0ODExMA==&mid=2247485152&idx=1&sn=bf10a95d75a9fc0e07711b1f1d9c264e&chksm=97851fc1a0f296d752282ddc1715702c4d08255d9f1808716aa15882bebf044ebad9b65f9cde&mpshare=1&scene=23&srcid=02066HNUNsio1Edejye0xmxF#rd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值