Zoe - Save the data dump
Zoe - Save the data dump

Reputation: 28288

Issues with zoom and Canvas using ScaleGestureDetector

I am trying to implement zoom in my app. But I have encountered difficulties.

What I have done so far:

(NOTE: this app is a game, so it does not use invalidate but a thread)

Rendering and the scaling:

public void render(Canvas c) {
    super.draw(c);

    if (c != null) {
        int ss = c.getSaveCount();
        c.scale(scaleFactor, scaleFactor);
        //Rendering stuff
        c.restoreToCount(ss);
    }
}

Current zoom:

(this is called from onTouchEvent in the master class when there are two pointers. THese classes are nested. )

class scaler extends ScaleGestureDetector {
    public scaler(Context context, OnScaleGestureListener listener) {
        super(context, listener);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        listener.onScale(this);
        return super.onTouchEvent(event);
    }

    @Override
    public float getScaleFactor() {
        return super.getScaleFactor();
    }
}
float startScale;
float endScale;
class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener{


        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            startScale = detector.getScaleFactor();
            scaleFactor *= detector.getScaleFactor();
            scaleFactor = (scaleFactor < 1 ? 1 : scaleFactor); // prevent our view from becoming too small //
            scaleFactor = ((float)((int)(scaleFactor * 100))) / 100; // Change precision to help with jitter when user just rests their fingers //
            return true;
        }

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {

        }


}

I have been looking on several questions on SO, and all I have found does not work properly. There are various reasons for the solutions.

The one I am currently using:

Zooms in before zooming out(the scalefactor drops down before zooming out)
It does not zoom in on the area the fingers are in.

So how can I add zoom that zooms in on the area the fingers are in, and make a it so it zooms without resetting the zoom so it is really zoomed in?

Upvotes: 1

Views: 1630

Answers (1)

Zoe - Save the data dump
Zoe - Save the data dump

Reputation: 28288

Thanks to @pskink, here is what I did to solve the problem:

  1. Don't override onTouchEvent in the class extending ScaleGestureDetector, and don't call OnScaleGestureListener.onScale as it is done automatically by the detector.

This solved the issues I had with zooming.

As for zooming in on a specific area, I had to move away from using .setScale, and use a matrix instead:

public void render(Canvas c) {
    super.draw(c);

    if (c != null) {

        c.setMatrix(scaleMatrix);//scale

        //Null the matrix = set to default. 
        c.setMatrix(null);//Past this line, anything rendered is not scaled. 

    }
}

(GestureDetector should not override onTouchEvent and make a call to the listener)

And in the listener:

    public boolean onScale(ScaleGestureDetector detector) {
        startScale = detector.getScaleFactor();
        scaleFactor *= detector.getScaleFactor();

        if(scaleFactor > 2) scaleFactor = 2;//Limit max
        else if(scaleFactor < 0.3f) scaleFactor = 0.3f;//limit min
        scaleFactor = ((float)((int)(scaleFactor * 100))) / 100;//jitter-protection
        scaleMatrix.setScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());//setScale, as I don't need to scale several things. 

        return true;
    }

Upvotes: 1

Related Questions