具有换行符的 BulletSpan 在 Android 中不起作用

BulletSpan which has newline is not working in Android

我正在使用自定义的 BulletSpan。 我想显示带有“\n”的长文本。 除了有'\n'的文本行外,每一行都很好。 bulleetspan 无法将缩进应用于换行文本。 这是结果。

最后一个文本是一个文本。并且文本里面有'\n'。

代码是..

class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    val source = listOf("Spans are powerful markup objects that you can use to style text at a character or paragraph level.",
    "By attaching spans to text objects, you can change text in a variety of ways, ",
    "including adding color, making the text clickable,\scaling the text size,\nand drawing text in a customized way.")

    val sb = SpannableStringBuilder()

    for (i in source.indices) {
        val length = sb.length
        sb.append(source[i])
        sb.append("\n")
        sb.setSpan(CustomBulletSpan(
            bulletRadius = dip(8),
            gapWidth = dip(14),
            mColor = color(),
            mWantColor = true
        ), length, length + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE)
    }

    binding.tvResult.text = sb

}

private fun dip(dp: Int): Int {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        dp.toFloat(),
        resources.displayMetrics
    ).toInt()
}

private fun color(): Int {
    return ContextCompat.getColor(applicationContext, R.color.gray);
} 
}

customBullentSpan 代码是..

class CustomBulletSpan(
val bulletRadius: Int = STANDARD_BULLET_RADIUS,
val gapWidth: Int = STANDARD_GAP_WIDTH,
val mColor: Int = STANDARD_COLOR,
val mWantColor: Boolean = false
) : LeadingMarginSpan {

companion object {
    // Bullet is slightly bigger to avoid aliasing artifacts on mdpi devices.
    private const val STANDARD_BULLET_RADIUS = 4
    private const val STANDARD_GAP_WIDTH = 2
    private const val STANDARD_COLOR = 0
}

private var mBulletPath: Path? = null


override fun getLeadingMargin(first: Boolean): Int {
    return 2 * bulletRadius + gapWidth
}

override fun drawLeadingMargin(
    c: Canvas,
    p: Paint,
    x: Int,
    dir: Int,
    top: Int,
    baseline: Int,
    bottom: Int,
    text: CharSequence,
    start: Int,
    end: Int,
    first: Boolean,
    layout: Layout?
) {
    if ((text as Spanned).getSpanStart(this) == start) {
        val style = p.style
        p.style = Paint.Style.FILL
        var oldColor = 0
        if (mWantColor) {
            oldColor = p.color
            p.color = mColor
        }

        val yPosition = if (layout != null) {
            val line = layout.getLineForOffset(start)
            layout.getLineBaseline(line).toFloat() - bulletRadius * 1.3f
        } else {
            (top + bottom) / 1.3f
        }

        val xPosition = (x + dir * bulletRadius).toFloat()

        if (c.isHardwareAccelerated) {
            if (mBulletPath == null) {
                mBulletPath = Path()
                mBulletPath!!.addCircle(0.0f, 0.0f, bulletRadius.toFloat(), Path.Direction.CW)
            }
            c.save()
            c.translate(xPosition, yPosition)
            c.drawPath(mBulletPath!!, p)
            c.restore()
        } else {
            c.drawCircle(xPosition, yPosition, bulletRadius.toFloat(), p)
        }

        if (mWantColor) {
            p.color = oldColor
        }

        p.style = style
    }
 }
}

我该如何解决这个问题??

您可以只获取字符串并按 \n 拆分并应用跨度

    var len = 0

    for (i in source.indices) {

        if (source[i].contains("\n")) {
            val splitted = source[i].split("\n")
            for (k in splitted.indices) {
                len = sb.length
                sb.append(splitted[k])
                sb.append("\n")
                sb.setSpan(
                        CustomBulletSpan(
                                bulletRadius = dip(8),
                                gapWidth = dip(14),
                                mColor = color(),
                                mWantColor = true
                        ), len, len + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE
                )
            }
        } else {
            len = sb.length
            sb.append(source[i])
            sb.append("\n")
            sb.setSpan(
                    CustomBulletSpan(
                            bulletRadius = dip(8),
                            gapWidth = dip(14),
                            mColor = color(),
                            mWantColor = true
                    ), len, len + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE
            )

        }
    }

另一种方法是将其拆分并添加到新列表并迭代相同的内容并应用跨度

  val newList = mutableListOf<String>()
    for (item in source) {
       if(item.contains("\n")) {
           val split = item.split("\n")
           for (splitItem in split){
               newList.add(splitItem)
           }
       } else{
           newList.add(item)
       }
    }