Search code examples
androidcustom-componentspannableimagespan

Custom ImageSpan not displaying properly


I'm trying to create a custom class that extends ImageSpan because I need some kind of margin/padding on the spans.

What I figured I need to do is to override the getSize function to return a bigger width so the spans get graphically spaced.

The problem is that as soon as I override the getSize function my view gets completely screwed up. My educated guess is then that I'm doing something stupid inside that funcion, but I can't get what.

Correctly displayed view

Wrong displayed view

Custom class code:

class PaddingImageSpan(drawable: Drawable, private val offset: Float = 0f) : ImageSpan(drawable) {

    override fun getSize(
        paint: Paint,
        text: CharSequence?,
        start: Int,
        end: Int,
        fm: Paint.FontMetricsInt?
    ): Int {

        val width = paint.measureText(text, start, end)
        val fontMetricsInt = paint.fontMetricsInt

        if (fm != null){
            fm.ascent = fontMetricsInt.ascent
            fm.bottom = fontMetricsInt.bottom
            fm.descent = fontMetricsInt.descent
            fm.leading = fontMetricsInt.leading
            fm.top = fontMetricsInt.top
        }

        println(width)

        return width.roundToInt()
    }
}

Solution

  • I figured it out. I'm posting the solution so if someone looks for it he can find it!

    My problem was I was using the text metrics instead of the drawable metrics.

    This is the correct code:

        override fun getSize(
            paint: Paint,
            text: CharSequence?,
            start: Int,
            end: Int,
            fm: Paint.FontMetricsInt?
        ): Int {
    
            val rect = drawable.bounds
    
            if (fm != null) {
                fm.ascent = -rect.bottom
                fm.descent = 0
    
                fm.top = fm.ascent
                fm.bottom = 0
            }
    
            return rect.right// + offset
    
        }
    

    That said, the cleaner way that I could come up with to space spannable is not by working on the spannable class but changing the setBounds() values.