Context: I had just added an interior map to my company’s app; It was zoomable, pannable and each point of interest was a clickable region. My next task was to implement a room highlighting feature.
This is what the finished product looks like:
I don’t care how it’s done, just give me the code already!
First off, we’ll want to subclass BitmapDrawable
; I named my new class “HighlightableBitmapDrawable” because I couldn’t think of anything better.
This is a very straightforward solution so let’s get to the meat of it.
- Override the
void draw(Canvas)
method. - If the selection rectangle is not null…
- …then clip the canvas to said rectangle.
- Dump your color of choice onto the canvas.
Op.DIFFERENCE
means that instead of clipping the canvas to inside our selection rectangle, we instead do the opposite: we clip the canvas to everything except the rectangle.
Cool, so our drawable can highlight an area by dimming its surrounding, but how do we set the selection? With setters!
Now you might be thinking: Great! This is exactly what I was looking for! Thanks Alex!, or rather: I’d prefer to use an overlay on the selected area, or even use both!
Well it’s your lucky day: adding in an overlay component is quite trivial!
Simply add a Bitmap
as a class member variable and draw it inside the selection area:
Add the relevant setters (or just add it to the constructor) and bam! You have an optional overlay that’ll be painted on top of the selection area. (If it doesn’t show, make sure the code to draw it is above the call to clipRect(..)
)
“But Alex”, I hear you cry, “I just wanted to paint a different colour on top, not a whole other image!”
We can do that too, but we’ll want to use canvas.save()
and canvas.restore()
to clear our previously clipped area:
To use this class in your code, simply create and instance so that you can change the selection area and then assign it to your ImageView with setImageDrawable(yourHighlightableDrawable)
.
That’s it! You should now be able to highlight regions of an ImageView with relatively little code and without needing to fiddle with additional views!
Here’s my source code for this: