Skip to content

Instantly share code, notes, and snippets.

@delacrixmorgan
Last active January 6, 2023 14:33
Show Gist options
  • Save delacrixmorgan/9185acf5e5a9b46ad40d597743c461c3 to your computer and use it in GitHub Desktop.
Save delacrixmorgan/9185acf5e5a9b46ad40d597743c461c3 to your computer and use it in GitHub Desktop.
Android SpanUtils - LeadingMarginSpan with Images
internal class DrawableMarginSpan : LeadingMarginSpan {
private val bitmap: Bitmap
private val verticalAlignment: Int
private val padding: Int
private val totalHeight = 0
constructor(bitmap: Bitmap, pad: Int, verticalAlignment: Int) {
this.bitmap = bitmap
padding = pad
this.verticalAlignment = verticalAlignment
}
constructor(drawable: Drawable, pad: Int, verticalAlignment: Int) {
bitmap = drawable2Bitmap(drawable)
padding = pad
this.verticalAlignment = verticalAlignment
}
constructor(uri: Uri, pad: Int, verticalAlignment: Int) {
bitmap = uri2Bitmap(uri)
padding = pad
this.verticalAlignment = verticalAlignment
}
constructor(resourceId: Int, pad: Int, verticalAlignment: Int) {
bitmap = resource2Bitmap(resourceId)
padding = pad
this.verticalAlignment = verticalAlignment
}
private fun drawable2Bitmap(drawable: Drawable): Bitmap {
if (drawable is BitmapDrawable) {
if (drawable.bitmap != null) {
return drawable.bitmap
}
}
val bitmap: Bitmap = if (drawable.intrinsicWidth <= 0 || drawable.intrinsicHeight <= 0) {
Bitmap.createBitmap(
1, 1,
if (drawable.opacity != PixelFormat.OPAQUE) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565
)
} else {
Bitmap.createBitmap(
drawable.intrinsicWidth, drawable.intrinsicHeight,
if (drawable.opacity != PixelFormat.OPAQUE) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565
)
}
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
return bitmap
}
private fun uri2Bitmap(uri: Uri): Bitmap {
return try {
MediaStore.Images.Media.getBitmap(instance.contentResolver, uri)
} catch (e: IOException) {
e.printStackTrace()
Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)
}
}
private fun resource2Bitmap(resourceId: Int): Bitmap {
val drawable = ContextCompat.getDrawable(instance, resourceId)
val canvas = Canvas()
val bitmap = Bitmap.createBitmap(drawable!!.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
canvas.setBitmap(bitmap)
drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
drawable.draw(canvas)
return bitmap
}
override fun getLeadingMargin(first: Boolean): Int {
return bitmap.width + padding
}
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
) {
var x = x
val st = (text as Spanned).getSpanStart(this)
val itop = layout.getLineTop(layout.getLineForOffset(st))
if (dir < 0) x -= bitmap.width
val delta = totalHeight - bitmap.height
if (delta > 0) {
if (verticalAlignment == ALIGN_TOP) {
c.drawBitmap(bitmap, x.toFloat(), itop.toFloat(), p)
} else if (verticalAlignment == ALIGN_CENTER) {
c.drawBitmap(bitmap, x.toFloat(), (itop + delta / 2).toFloat(), p)
} else {
c.drawBitmap(bitmap, x.toFloat(), (itop + delta).toFloat(), p)
}
} else {
c.drawBitmap(bitmap, x.toFloat(), itop.toFloat(), p)
}
}
companion object {
const val ALIGN_CENTER = 2
const val ALIGN_TOP = 3
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment