2

I am using magnifier view for my application which is a library I got from here :

https://github.com/nomanr/android-image-magnifier

I have modified this class to extend FrameLayout (It was ImageView before) to work on my FrameLayout.

It's working well except the painted canvas view stays back of all the views which are added in that custom view.

How to bring that canvas on front of those added views?

Custom view class that i am using :

public class ImageMagnifier extends FrameLayout {

private PointF zoomPos;
private boolean zooming = false;
private Matrix matrix;
private Paint paint;
private Bitmap bitmap;
private BitmapShader shader;
private int sizeOfMagnifier = 300;
int cheight, cwidth;

Context con;
C c = C.getInstance();
public ImageMagnifier(Context context) {
    super(context);
    init();
    con=context;
}

public ImageMagnifier(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
    con=context;
}

public ImageMagnifier(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
    con=context;
}

private void init() {
    zoomPos = new PointF(0, 0);
    matrix = new Matrix();
    paint = new Paint();

    cwidth = c.Width * 109 / 1280;
    cheight = cwidth * 134 / 109;
}

public void otherTouch(int x, int y) {
    if (x > c.getwidth1(28) && x < c.getwidth1(921) && y > c.getheight1(135) && y < c.getheight1(560)) {
        zoomPos.x = x - 10;
        zoomPos.y = y - 75;
        zooming = true;
        this.invalidate();

    } else {
        RemoveMagnifire();
    }
}

public void RemoveMagnifire() {
    zooming = false;
    this.invalidate();
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (!zooming) {
        buildDrawingCache();
    } else {

        bitmap = getDrawingCache();
        shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);        
        paint.setShader(shader);
        matrix.reset();
        matrix.postScale(2f, 2f, zoomPos.x-10, zoomPos.y+60);

        paint.getShader().setLocalMatrix(matrix);

        int width = c.Width;
        int height = c.Height;

        float leftX = zoomPos.x - ((width * 100) / 1280);
        float topY = zoomPos.y - ((height * 250) / 720);
        float rightX = zoomPos.x +  ((width * 100) / 1280);
        float bottomY = zoomPos.y - ((height * 100) / 720);

        canvas.drawRect(leftX , topY, rightX, bottomY, paint);


    }
}

}
Prashant
  • 1,593
  • 1
  • 17
  • 32

1 Answers1

2

A ViewGroup draws its child Views in the dispatchDraw() method. We just need to move the magnifier drawing to after that happens.

The fix is simple. Move everything after the super call in onDraw() to after the super call in dispatchDraw().

...

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // Removed
}

@Override
protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);

    if (!zooming) {
        buildDrawingCache();
    }
    else {
        bitmap = getDrawingCache();
        shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        paint.setShader(shader);
        matrix.reset();
        matrix.postScale(2f, 2f, zoomPos.x - 10, zoomPos.y + 60);

        paint.getShader().setLocalMatrix(matrix);

        int width = c.Width;
        int height = c.Height;

        float leftX = zoomPos.x - ((width * 100) / 1280);
        float topY = zoomPos.y - ((height * 250) / 720);
        float rightX = zoomPos.x +  ((width * 100) / 1280);
        float bottomY = zoomPos.y - ((height * 100) / 720);

        canvas.drawRect(leftX , topY, rightX, bottomY, paint);
    }
}

...

You can just remove the onDraw() override, if you no longer need it for anything else.

Mike M.
  • 38,532
  • 8
  • 99
  • 95
  • ok, its working thanks for the solution. how can we remove canvas transparency ? drawRect() draws rectangle perfectly but it have some transparency. – Prashant Jun 30 '16 at 13:59
  • 1
    Yeah, it'll do that if you've not set a background for your custom `View`, since it'll have a transparent background by default. You can draw another `Rect` right before the other one, with the same dimensions and location, but with a different `Paint` object, with its color set to whatever you want, with the `Paint#setColor()` method. – Mike M. Jun 30 '16 at 14:04
  • Well, a possible fix would be to override the `addView(View, int, ViewGroup.LayoutParams)` method, and call `destroyDrawingCache()` there. Not sure how you were getting a `StackOverflowError`, though. – Mike M. Jul 01 '16 at 10:32