Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set bullet radius in BulletSpan below api level 28?

Tags:

android

How to use BulletSpan(gapWidth, color, bulletRadius), below api level 28? I am unable to set bulletRadius below api level 28. Any help would be appreciated.

like image 209
Rahul Gupta Avatar asked Jul 16 '19 13:07

Rahul Gupta


2 Answers

So the method with radius parameters do not appear until API level 28. For previous APIs, you can refer to this article.

Basically what the author did was porting the API 28+ BulletSpan to your app project so you can use the ported version to achieve setting the radius.

like image 154
HarryQ Avatar answered Sep 21 '22 02:09

HarryQ


Writing a Custom Bullet Span works like a charm, because you will get the canvas in your hand. With this you can paint a bullet of any kind/size to your view.

 open class CharBulletSpan(var charCode: String, gapWidth: Int, internal val bulletColor: Int, val bulletSize: Int, val alignment: Layout.Alignment,val typeface: Typeface) : BulletSpan(gapWidth, bulletColor) {
   private var isSpanStart = true
   private val space = gapWidth
   var alpha = 0f
    override fun getLeadingMargin(first: Boolean): Int { // Returns the amount of indentation as set by the LeadingMarginSpan.class
      if (!first) {
        return 0
      }
      return super.getLeadingMargin(first)
   }
     
    override fun drawLeadingMargin(canvas: Canvas, paint: Paint, x: Int, dir: Int, top: Int, baseline: Int, bottom: Int, text: CharSequence, start: Int, end: Int, first: Boolean, layout: Layout?) {
    //This is where the magic happens. Let us get the x - translation for the bullet since we will be painting on the canvas for different text alignments
    
       isSpanStart = (text as Spanned).getSpanStart(this) == start
       val xPos = getBulletXPos(layout!!, start, x)

       val selectionStart = Selection.getSelectionStart(text)
       val selectionEnd = Selection.getSelectionEnd(text)

       //The following block is just for a fancy purpose. When we type text and press enter and the cursor is in a new line, we can apply an alpha value to the bullet/ set a transparency. If text is typed in that line , the bullet's alpha value can be changed.
       if (!text.isNullOrEmpty()) {
        if (start != end && (text.subSequence(start, end).isNotEmpty() && text.subSequence(start, end) != "\n")) {
            this.alpha = 255f
        }
        if (start == end) {
            if ((start == 1 && selectionStart == 0) || (start == selectionStart && end == selectionEnd)) { // first line
                this.alpha = 150f
                if (!isCursorVisible) {
                    this.alpha = 0f
                }
            } else if (selectionStart != start) {
                this.alpha = 0f
            }
        }
      } else if (text != null && text.isEmpty() && start == 0 && start == end) {
          this.alpha = 255f
      }
       if (isSpanStart) {
        // Now we shall fire the bullet
           renderCharBullet(canvas, paint, xPos, dir, top, baseline, bottom, text,charCode)
        }

     }

    private fun getBulletXPos(layout: Layout, start: Int, x: Int): Int {
    val width = layout.width
    val lineNo = layout.getLineForOffset(start)
    val lineLeft = layout.getLineLeft(lineNo)
    val lineWidth = layout.getLineWidth(lineNo)
    return when (alignment) {
        Layout.Alignment.NORMAL -> x
        Layout.Alignment.OPPOSITE -> x + (width - lineWidth).toInt()
        Layout.Alignment.ALIGN_CENTER -> lineLeft.toInt() - space
        else -> x
    }
}

   private fun renderCharBullet(canvas: Canvas?, paint: Paint?, x: Int, dir: Int, top: Int, baseline: Int, bottom: Int, text: CharSequence?, charCode: String) {
    val rectF = Rect()
    val newPaint = Paint()
    newPaint.typeface = typeface
    newPaint.textSize = bulletSize
    //Constructing a new paint to compute the y - translation of the bullet for the current line
    if (!text.isNullOrEmpty()) {
        newPaint.getTextBounds(text.subSequence(0, 1).toString(), 0, text.subSequence(0, 1).length, rectF)
    }
    val oldStyle = paint?.style
    paint?.textSize = bulletSize
    paint?.typeface = typeface
    paint?.style = Paint.Style.FILL
    paint?.color = bulletColor
    paint?.alpha = alpha.toInt()


    if (canvas!!.isHardwareAccelerated) {
        canvas.save()
        canvas.translate((x + dir).toFloat(), baseline - rectF.height().div(2.0f))
        canvas.drawText(charCode, 0f, rectF.height().div(2.0f), paint!!)
        canvas.restore()
    }
    paint?.style = oldStyle
}

}
like image 34
Manasa Murali Avatar answered Sep 22 '22 02:09

Manasa Murali