I am drawing lines on an ImageView by doing something like this:
Bitmap imageBitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
Bitmap duplicateBitmap = Bitmap.createBitmap(imageBitmap.getWidth(),imageBitmap.getHeight(),Bitmap.Config.RGB_565);
Canvas targetCanvas = new Canvas(duplicateBitmap);
targetCanvas.drawBitmap(imageBitmap,0,0,null);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(3f);
targetCanvas.drawLine(0f,100f, imageBitmap.getWidth(),100f,paint);
imageView.setImageDrawable(new BitmapDrawable(getResources(),duplicateBitmap));
Which looks okay when not zoomed in.
But when I zoom in the line becomes thick. (Which is expected behavior)
Now, how to draw lines on an image view so that when the user zooms in the thickness of the line is unaffected?
P.S: I tried "zooming in" the image first and then draw lines on the image. (upon button click or something). But that didn't work, the line was still very thick.
I also found that when the image is of lower resolution the drawn lines are thicker. So I assume that drawing on an image is somehow related to image resolution too.
I was thinking of masking the ImageView with a high res canvas but that would be memory inefficient. Also, I am clueless about how to actually implement this.
I somehow believe that the answers to this question can solve my problem.
The correct approach is to render the lines dynamically using a View canvas, and not into the bitmap itself.
The reason why your implementation fails, is because if you render the grid directly into the bitmap, then you are effectively changing the bitmap pixels, so logically if you zoom the bitmap then the grid pixels will also zoom, as everything bitmap + grid have become the same single image.
A solution can be to use any ready-made zoom image view widget. You'll find lots in GitHub such as for example:
ZoomImageView
Then you have 2 options, to extend the widget to create your own subclass, or to perform the implementation directly into the widget code. Is up to you.
What you need to do in any of both cases, is to override its onDraw callback, and perform the grid drawing right after the super.onDraw(canvas) call. No need to create new bitmaps or new canvas instances. Use the method's canvas to perform the drawing.
@Override
protected void onDraw(final Canvas canvas) {
super.onDraw(canvas);
// Render the grid
final int slotWidth = this.getWidth() / 3;
final int slotHeight = this.getHeight() / 3;
this.paint.setColor(this.gridColor);
// Horizontal lines
canvas.drawLine(0, slotHeight, this.getWidth(), slotHeight, this.paint);
canvas.drawLine(0, (slotHeight * 2), this.getWidth(), (slotHeight * 2), this.paint);
// Vertical lines
canvas.drawLine(slotWidth, 0, slotWidth, this.getHeight(), this.paint);
canvas.drawLine((slotWidth * 2), 0, (slotWidth * 2), this.getHeight(), this.paint);
}
As a side note, avoid creating new objects inside the onDraw method, such as Paint instances, etc. as the onDraw can be called several times in a short period. Lint should warn you anyway about this. Never create new object instances in methods such as onDraw, onMeasure, etc., for such scenarios always precache/reuse them.
A simpler alternative, is to extend a View and create a new dedicated grid view widget, unrelated to the actual Zoom Image View. Perform the same, so, also override the onDraw method as the above example, and render the grid as shown. Then place this new View into your layout design, exactly on top of your Zoom Image View control, ensuring both controls have the same metrics.
Use this TouchImageView library for zooming and detecting the zoom via OnTouchImageViewListener
and isZoomed()
. If zoomed, then redraw the canvas using the zoomed area. This is the code:
touchImageView.setOnTouchImageViewListener(() -> {
if (touchImageView.isZoomed()){
//gets the zoomed area
Bitmap result = Bitmap.createBitmap(touchImageView.getWidth(), touchImageView.getHeight(), Bitmap.Config.RGB_565);
Canvas c = new Canvas(result);
touchImageView.draw(c);
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With