一、主要解决的使用场景

1,UI可能会设计一段文本,部分字体跟整段文本的样式不一样,例如很多app登陆首页都需要显示用户协议和隐私政策并且需要能够点击。

2,遇到需要翻译多个国家语言的,每个国家的语言字符长度不一样,所以没办法通过字符所在字符串中的位置去设置样式(除非你为每个语言做适配)。如果采用多个TextView拼接的方式,多国语言语法不一,这将会导致语序不对,而且字符串一旦长了换行也是个问题。

二、支持功能

1、本库支持字体设置字体颜色甚至渐变色,加粗,斜体,下划线,删除线,字体大小

2、本库支持下划线支持设置线宽,距离文字距离,下划线颜色

3、本库支持删除线支持设置线宽,删除线颜色

4、本库支持设置图片,大小,左右距离,加载本地、网络图片

5、支持给每个位置的富文本添加点击事件

6、支持给每个位置的富文本设置背景色

android tablelayout 字体加粗 BUG 安卓textview字体加粗_android

  

android tablelayout 字体加粗 BUG 安卓textview字体加粗_html_02

三、实现原理

1,把需要设置单独样式的文本替换为变量,例如:

        我已阅读并同意《用户协议》和《隐私政策》

提取文字为:

val agreeText = "我已阅读并同意%1$s和%2$s";

2,接下啦我将会为以上两个变量赋值为 《用户协议》和《隐私政策》

        第1步,将《用户协议》《隐私政策》替换为

val str1 = "<a href=\"0\">《用户协议》</a>"    
val str2 = "<a href=\"1\">《隐私政策》</a>"

         第2步,把 str1str2 赋值给 agreeText

val richText = String.format(textValue, str1,str2)

这时richText已经带有html标签的字符串了

3,设置样式

//获取富文本
val spannedHtml = Html.fromHtml(richText)//富文本

val htmlBuilder = SpannableStringBuilder(spannedHtml)
//得到刚才两个文本数组了
val spans = htmlBuilder.getSpans(0, spannedHtml.length,URLSpan::class.java)
//给每个span设置样式
for (i in spans.indices) {
    val urlSpan = spans[i]
    val pos = span.url.toInt()
//  pos就是上边a标签的href设置的下标根据这个去找对应的样式
    val start = htmlBuilder.getSpanStart(urlSpan)
    val end = htmlBuilder.getSpanEnd(urlSpan)
    val flags = htmlBuilder.getSpanFlags(urlSpan)

    val clickableSpan: ClickableSpan = object : ClickableSpan() {
         override fun onClick(widget: View) {
             val url = urlSpan.url
             //回调点击事件
             onFormatClickListener?.onLabelClick(url.toInt())
             isClickSpanItem = true
         }

         override fun updateDrawState(ds: TextPaint) {
             super.updateDrawState(ds)
             //设置颜色
             if (color != 0) {
                 ds.color = resources.getColor(color)
             } else {
                 ds.color = currentTextColor
             }
             //设置是否要下划线
             ds.isUnderlineText = underline
        }
    }  
    //设置点击事件
    htmlBuilder.setSpan(clickableSpan, start, end, flags)
    //设置字体大小
    htmlBuilder.setSpan(AbsoluteSizeSpan(textSize,true), start, end, flags)
    //设置字体加粗
    htmlBuilder.setSpan(StyleSpan(Typeface.BOLD), start, end, flags)
    //设置字体斜体
    htmlBuilder.setSpan(StyleSpan(Typeface.ITALIC), start, end, flags)
}

四、结束语

        其实原理很简单,把想要设置单独样式文本提取出来替换为富文本,为每个富文本设置单独的样式

使用方法:

1,设置文本和样式

textView.setFormatTextBean(R.string.test_text,
            FormatText().setColor(R.color.colorAccent).setBold(true).setUnderline(true).setItalic(true).setResValue(R.string.we).setTextSize(30),
            FormatText().setColor(R.color.colorPrimaryDark).setBold(true).setUnderline(false).setItalic(false).setStrValue("you"))

2,设置监听

textView.setOnFormatClickListener(object : OnFormatClickListener{
            override fun onLabelClick(position: Int) {//position就是设置数据的顺序
                Toast.makeText(this@MainActivity,"onItemClick-item"+position,Toast.LENGTH_SHORT).show()
            }
        })