Last active
January 6, 2023 14:33
-
-
Save delacrixmorgan/9185acf5e5a9b46ad40d597743c461c3 to your computer and use it in GitHub Desktop.
Android SpanUtils - LeadingMarginSpan with Images
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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