Reputation: 28288
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
Reputation: 28288
Thanks to @pskink, here is what I did to solve the problem:
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