Prashant Prashant - 5 months ago 24
Android Question

How to bring canvas on top of other views

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);


}
}

}

Answer

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.