程序猿老张 發表於 2019-7-22 18:47:00

Android开发 SpannableString 与 SpannableStringBuilder开发详解

<h1><span style="color: rgba(0, 128, 128, 1)">版权声明</span></h1>
<p>本文来自博客园,作者:观心静&nbsp;,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/11227711.html</p>
<div>本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。</div>
<h1><span style="color: rgba(0, 128, 128, 1)">前言</span></h1>
<p>  SpannableString,是google提供用来处理富文本的功能类.支持很多文本内容的效果变化.另外,它也是Android实现富文本编辑器的关键.</p>
<p>  SpannableStringBuilder是用于实现多个SpannableString拼接的实现类,类似于Java的StringBuilder。此类下面也会简单说明,主要还是了解SpannableString。</p>
<h1><span style="color: rgba(0, 128, 128, 1)">关键API详解</span></h1>
<div class="cnblogs_code">
<pre>     String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span> ForegroundColorSpan(Color.parseColor("#FFFF0C00"<span style="color: rgba(0, 0, 0, 1)">))
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p>&nbsp;</p>
<p>这是一个简单使用的demo,我们用这个demo来讲解一些关键点.</p>
<p>这行代码的关键是<strong><span style="color: rgba(0, 0, 0, 1)">setSpan(Object what, int start, int end, int flags)</span></strong>方法,这个方法在后面的文字处理将会一直使用到. <span style="color: rgba(0, 0, 0, 1)">setSpan有四个参数我们一个一个来讲解:</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">第一个参数 <strong><span style="color: rgba(0, 0, 0, 1)">Object what</span></strong> 这个参数主要是提供你需要改变字符串的效果实现类,后续会一一讲解并且给出效果图</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">第二个参数 <strong><span style="color: rgba(0, 0, 0, 1)">int start </span></strong><span style="color: rgba(0, 0, 0, 1)">这个参数是需要改变的字符串的<strong>起始位置</strong></span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">第三个参数 <strong><span style="color: rgba(0, 0, 0, 1)"> int end </span></strong><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">这个参数是需要改变的字符串的<strong>结束位置</strong></span></span></span></span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">第四个参数 <strong><span style="color: rgba(0, 0, 0, 1)"> int flags</span></strong> 是一些字符串新增效果的影响范围,您可以参考这篇博客<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">https://www.jianshu.com/p/1956e15c9a27</span></span></span></span></span></span></span></span></span></span>这位大神讲解的十分详细了.本着就算是看懂了也要敲一敲代码记录的想法,下面也会说明一下常用的4种方法<br></span></span></span></span></span></p>
<h4><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 128, 128, 1)">public static final int SPAN_INCLUSIVE_EXCLUSIVE = SPAN_MARK_MARK;&nbsp;</span> </span></h4>
<p><span style="color: rgba(0, 0, 0, 1)">在前面/范围内增加字符,新增字符会跟随效果. </span></p>
<p><span style="color: rgba(0, 0, 0, 1)">在后面增加字符,新增字符不会跟随效果</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">效果图:</span></p>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722201859788-848828153.gif" alt=""></p>
<h4><span style="color: rgba(0, 128, 128, 1)">public static final int SPAN_INCLUSIVE_INCLUSIVE = SPAN_MARK_POINT;</span></h4>
<p><span style="color: rgba(0, 0, 0, 1)">在前面/范围内/后面<span style="color: rgba(0, 0, 0, 1)">增加字符,新增字符会跟随效果. </span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">效果图:</span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722202202845-452672941.gif" alt=""></span></span></p>
<h4><span style="color: rgba(0, 128, 128, 1)">public static final int SPAN_EXCLUSIVE_EXCLUSIVE = SPAN_POINT_MARK;</span></h4>
<p><span style="color: rgba(0, 0, 0, 1)">在范围内<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">增加字符,新增字符会跟随效果. </span></span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">在前面/后面增加字符,新增字符不会跟随效果</span></span></span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">效果图:</span></span></span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722202443221-106425521.gif" alt=""></span></span></span></span></p>
<h4><span style="color: rgba(0, 128, 128, 1)">public static final int SPAN_EXCLUSIVE_INCLUSIVE = SPAN_POINT_POINT;</span></h4>
<p><span style="color: rgba(0, 0, 0, 1)">在范围内/后面<span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">增加字符,新增字符会跟随效果. </span></span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">在前面增加字符,新增字符不会跟随效果.</span></span></span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">效果图:</span></span></span></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722202609063-2134854044.gif" alt=""></span></span></span></span></p>
<p>&nbsp;</p>
<p><span style="color: rgba(0, 0, 0, 1)">代码里还有一些其他的常量,但是测试后其他都是这四种基本里一样的效果.也实在是没看懂google的注释.....<br></span></p>
<h1><span style="color: rgba(0, 128, 128, 1)">文字颜色</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">以下代码将一段文字变成红色</span></p>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span> ForegroundColorSpan(Color.parseColor("#FFFF0C00"<span style="color: rgba(0, 0, 0, 1)">))
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);    </span></pre>
</div>
<p>&nbsp;</p>
<p>ForegroundColorSpan 注意这个类是关键,他实现文字颜色改变.</p>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722205147528-218491381.png" alt=""></p>
<h1><span style="color: rgba(0, 128, 128, 1)">文字背景颜色</span></h1>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span> BackgroundColorSpan(Color.parseColor("#FFFF0C00"<span style="color: rgba(0, 0, 0, 1)">))
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p>&nbsp;</p>
<p>BackgroundColorSpan&nbsp;注意这个类是关键,他实现文字背景颜色改变.</p>
<p><span style="color: rgba(0, 0, 0, 1)">效果图:</span></p>
<p><span style="color: rgba(0, 128, 128, 1)"><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722205222078-692653505.png" alt=""></span></p>
<h1><span style="color: rgba(0, 128, 128, 1)">字体</span></h1>
<p>&nbsp;</p>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span> TypefaceSpan("sans-serif") <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">new TypefaceSpan(Typeface.SANS_SERIF) 或者使用这个方法</span>
                , content.indexOf("创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p>&nbsp;</p>
<p>效果图(系统自带的演示字体效果不明显):</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190723101425885-1949434465.png" alt=""></p>
<p>&nbsp;</p>
<h1><span style="color: rgba(0, 128, 128, 1)">字体大小</span></h1>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span> AbsoluteSizeSpan(50<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);    </span></pre>
</div>
<p>&nbsp;</p>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722205415505-1743223378.png" alt=""></p>
<p>&nbsp;</p>
<h1><span style="color: rgba(0, 128, 128, 1)">粗体</span></h1>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StyleSpan(Typeface.BOLD)
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p><span style="color: rgba(0, 0, 0, 1)">效果图:</span></p>
<p><span style="color: rgba(0, 128, 128, 1)"><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722205730217-1285692889.png" alt=""></span></p>
<h1><span style="color: rgba(0, 128, 128, 1)">斜体</span></h1>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StyleSpan(Typeface.ITALIC)
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p>&nbsp;</p>
<p><span style="color: rgba(0, 0, 0, 1)">效果图:</span></p>
<p><span style="color: rgba(0, 128, 128, 1)"><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722205847503-78275424.png" alt=""></span></p>
<h1><span style="color: rgba(0, 128, 128, 1)">粗体和斜体</span></h1>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StyleSpan(Typeface.BOLD_ITALIC)
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p>&nbsp;</p>
<p>另外还有一个<span style="color: rgba(0, 0, 0, 1)">Typeface</span>.NORMAL&nbsp; 正常值就不演示了</p>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722210030960-1928121076.png" alt=""></p>
<p>&nbsp;</p>
<h1><span style="color: rgba(0, 128, 128, 1)">删除线</span></h1>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> StrikethroughSpan()
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p>&nbsp;</p>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722210242379-816113998.png" alt=""></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1><span style="color: rgba(0, 128, 128, 1)">下划线</span></h1>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> UnderlineSpan()
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722210446582-1413895225.png" alt=""></p>
<h1><span style="color: rgba(0, 128, 128, 1)">上标</span></h1>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SuperscriptSpan()
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190723101800978-940346094.png" alt=""></p>
<h1><span style="color: rgba(0, 128, 128, 1)">下标</span></h1>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SubscriptSpan()
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190723101639730-1234520382.png" alt=""></p>
<h1><span style="color: rgba(0, 128, 128, 1)">插入图片</span></h1>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      Bitmap bitmap </span>=<span style="color: rgba(0, 0, 0, 1)"> BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
      ImageSpan span </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ImageSpan(bitmap);
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(span
                , </span>0<span style="color: rgba(0, 0, 0, 1)">
                , </span>1<span style="color: rgba(0, 0, 0, 1)">
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p>或者</p>
<div class="cnblogs_code">
<pre>      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      Drawable drawable </span>= getResources().getDrawable(R.mipmap.ic_launcher, <span style="color: rgba(0, 0, 255, 1)">null</span>); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">读取图片</span>
      drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置边界 图片显示范围</span>
      ImageSpan span = <span style="color: rgba(0, 0, 255, 1)">new</span> ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ImageSpan.ALIGN_BASELINE 是对齐方式,这个是基线对齐</span>
      SpannableString spannableString = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(span
                , </span>0<span style="color: rgba(0, 0, 0, 1)">
                , </span>1<span style="color: rgba(0, 0, 0, 1)">
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p>效果图:</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190722212003528-1660325294.png" alt=""></p>
<h1><span style="color: rgba(0, 128, 128, 1); background-color: rgba(255, 255, 255, 1)">点击事件</span></h1>
<div class="cnblogs_code">
<pre>      mTextView.setMovementMethod(LinkMovementMethod.getInstance());<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这是关键,只有TextView添加这个后才能有点击事件</span>
      mTextView.setHighlightColor(getResources().getColor(R.color.fontRed, <span style="color: rgba(0, 0, 255, 1)">null</span>));<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">修改点击后的背景色</span>
      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      ClickableSpan clickableSpan </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ClickableSpan() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onClick(@NonNull View widget) {
                Toast.makeText(MainActivity.</span><span style="color: rgba(0, 0, 255, 1)">this</span>, "你点击了创业未半"<span style="color: rgba(0, 0, 0, 1)">, Toast.LENGTH_SHORT).show();
            }

            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> updateDrawState(@NonNull TextPaint ds) {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">改变选中文字的颜色或者样式,注意这里的TextPaint 其实是Paint,可以参考Paint的绘制添加其他效果.</span>
<span style="color: rgba(0, 0, 0, 1)">                ds.setColor(Color.RED);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">                super.updateDrawState(ds);</span>
<span style="color: rgba(0, 0, 0, 1)">            }
      };
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(clickableSpan
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p><span style="color: rgba(255, 0, 0, 1)"><strong>setMovementMethod是重中之重,只有设置了才能有 点击功能</strong></span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><strong>另外,如果你需要设置文字的各种样式,比如 <span style="color: rgba(255, 0, 0, 1)">取消下划线 ds.setUnderlineText(false) </span>改变 <span style="color: rgba(255, 0, 0, 1)">字体颜色</span> 请在updateDrawState(@NonNull TextPaint ds) 方法里设置</strong></span></p>
<p>效果图:</p>
<p><strong><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190723111256480-887259333.gif" alt=""></strong></p>
<h1><span style="color: rgba(0, 128, 128, 1); background-color: rgba(255, 255, 255, 1)">超链接 </span></h1>
<h3>&nbsp;电话</h3>
<div class="cnblogs_code">
<pre>      mTextView.setMovementMethod(LinkMovementMethod.getInstance());<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这是关键,只有TextView添加这个后才能有点击事件</span>
      mTextView.setHighlightColor(getResources().getColor(R.color.fontRed, <span style="color: rgba(0, 0, 255, 1)">null</span>));<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">修改点击后的背景色</span>
      String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString spannableString </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(content);
      spannableString.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span> URLSpan("tel:10086"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"创业"<span style="color: rgba(0, 0, 0, 1)">)
                , content.indexOf(</span>"而中"<span style="color: rgba(0, 0, 0, 1)">)
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      mTextView.setText(spannableString);</span></pre>
</div>
<p><strong>注意!使用超链接,依然要设置setMovementMethod,</strong>另外URLSpan也是可以重写点击事件的.</p>
<p>&nbsp;效果图:</p>
<p>&nbsp;<img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190723111630617-1271546096.gif" alt=""></p>
<p>与使用Intent的超链接类似,也是支持几个通用的超链接,都需要你输入正确的<strong>前缀</strong></p>
<ul>
<li><code>mailto:123456@qq.com</code></li>
<li><code><code>http://www.baidu.com</code></code></li>
<li><code>sms:123456</code></li>
<li><code>mms:123456</code></li>
<li><code>geo: 38.899533,-77.036476</code></li>
</ul>
<p>&nbsp;</p>
<h1><span style="color: rgba(0, 128, 128, 1)">SpannableStringBuilder 的功能使用</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">这个类是用于实现多个SpannableString文字拼接的。这里举一个例子进行说明,假如我们要实现下面图片的效果:</span></p>
<p><span style="color: rgba(0, 0, 0, 1)"><img src="https://img2020.cnblogs.com/blog/1497956/202011/1497956-20201118200920447-686851806.png" alt=""></span></p>
<p>用户协议与隐私政策需要分别的点击效果。</p>
<p>代码如下:</p>
<div class="cnblogs_code">
<pre>    <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> initAgreementAndPrivacy() {
      SpannableStringBuilder builder </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableStringBuilder();
      builder.append(</span>"进入系统即同意"<span style="color: rgba(0, 0, 0, 1)">);

      String userAgreement </span>= "《用户协议》"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString userAgreementSpannable </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(userAgreement);
      userAgreementSpannable.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ClickableSpan() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onClick(@NonNull View widget) {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">用户协议点击</span>
<span style="color: rgba(0, 0, 0, 1)">            }

            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> updateDrawState(@NonNull TextPaint ds) {
                </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.updateDrawState(ds);
                ds.setColor(Color.WHITE);
                ds.setUnderlineText(</span><span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
            }
      }, </span>0<span style="color: rgba(0, 0, 0, 1)">, userAgreement.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

      builder.append(userAgreementSpannable);
      builder.append(</span>"和"<span style="color: rgba(0, 0, 0, 1)">);
      String privacyPolicy </span>= "《隐私政策》"<span style="color: rgba(0, 0, 0, 1)">;
      SpannableString privacyPolicySpannable </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SpannableString(privacyPolicy);
      privacyPolicySpannable.setSpan(</span><span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ClickableSpan() {
            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> onClick(@NonNull View widget) {
                </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">隐私政策点击</span>
<span style="color: rgba(0, 0, 0, 1)">
            }

            @Override
            </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> updateDrawState(@NonNull TextPaint ds) {
                </span><span style="color: rgba(0, 0, 255, 1)">super</span><span style="color: rgba(0, 0, 0, 1)">.updateDrawState(ds);
                ds.setColor(Color.WHITE);
                ds.setUnderlineText(</span><span style="color: rgba(0, 0, 255, 1)">false</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">取消下划线</span>
<span style="color: rgba(0, 0, 0, 1)">            }
      }, </span>0<span style="color: rgba(0, 0, 0, 1)">, userAgreement.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      builder.append(privacyPolicySpannable);
      mArguementText.setMovementMethod(LinkMovementMethod.getInstance());
      mArguementText.setHighlightColor(getResources().getColor(android.R.color.transparent, </span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">));
      mArguementText.setText(builder);
    }</span></pre>
</div>
<p>&nbsp;</p>
<h1><span style="color: rgba(0, 128, 128, 1)">其他Span</span></h1>
<p>  上面的span只是一些常用的span演示,但是其实还有更多的span可以选择和使用,他们都在<img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190723112537790-1033711594.png" alt="">这个目录中.在这个目录下还有以下这些span.如果后续有时间我会一一实验使用这些span以判断他们的功能.</p>
<p><img src="https://img2018.cnblogs.com/blog/1497956/201907/1497956-20190723112624814-2109262400.png" alt=""></p>
<h1><span style="color: rgba(0, 128, 128, 1)">放弃富文本效果,提取文本</span></h1>
<p><span style="color: rgba(0, 0, 0, 1)">之前有端时间苦恼怎么提取不带富文本格式的文本,因为源代码的有很多方法并没有注释,所以蛋疼了很久..,后面突然发现,直接使用toString()方法就行</span></p>
<div class="cnblogs_code">
<pre>spannableString.toString()</pre>
</div>
<p>&nbsp;</p>
<p><span style="color: rgba(0, 128, 128, 1)">END</span></p>
<pre class="highlighter-hljs" data-dark-theme="true"><code>SpannableStringBuilder</code></pre>

</div>
<div id="MySignature" role="contentinfo">
    <div style="text-align: center">
    <p style="color:orange;font-size:16px;" >本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/11227711.html </p>
    <div style="color:orange;font-size:16px;">本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。 </div>
</div><br><br>
来源:https://www.cnblogs.com/guanxinjing/p/11227711.html
頁: [1]
查看完整版本: Android开发 SpannableString 与 SpannableStringBuilder开发详解