Wdrażanie powiększania i przeciągania przy użyciu kompilacji gestów w systemie Android i słuchacza skali
Usiłuję zaimplementować powiększanie i przeciąganie za pomocą nasłuchiwania gestów systemu Android i detektora skali. Problem polega na tym, że kiedy wykonuję powiększenie szczypiące, obraz (który próbuję powiększyć) odbija się do określonej lokalizacji. Również pozycja zoomu nie jest wyśrodkowana. Poniższy kod pokazuje, co próbuję osiągnąć. Jakiś pomysł, dlaczego obraz skacze (i jak go poprawić)?
public class CustomView extends View {
Bitmap image;
int screenHeight;
int screenWidth;
Paint paint;
GestureDetector gestures;
ScaleGestureDetector scaleGesture;
float scale = 1.0f;
float horizontalOffset, verticalOffset;
int NORMAL = 0;
int ZOOM = 1;
int DRAG = 2;
boolean isScaling = false;
float touchX, touchY;
int mode = NORMAL;
public CustomView(Context context) {
super(context);
//initializing variables
image = BitmapFactory.decodeResource(getResources(),
R.drawable.image_name);
//This is a full screen view
screenWidth = getResources().getDisplayMetrics().widthPixels;
screenHeight = getResources().getDisplayMetrics().heightPixels;
paint = new Paint();
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
paint.setColor(Color.WHITE);
scaleGesture = new ScaleGestureDetector(getContext(),
new ScaleListener());
gestures = new GestureDetector(getContext(), new GestureListener());
mode = NORMAL;
initialize();
}
//Best fit image display on canvas
private void initialize() {
float imgPartRatio = image.getWidth() / (float) image.getHeight();
float screenRatio = (float) screenWidth / (float) screenHeight;
if (screenRatio > imgPartRatio) {
scale = ((float) screenHeight) / (float) (image.getHeight()); // fit height
horizontalOffset = ((float) screenWidth - scale
* (float) (image.getWidth())) / 2.0f;
verticalOffset = 0;
} else {
scale = ((float) screenWidth) / (float) (image.getWidth()); // fit width
horizontalOffset = 0;
verticalOffset = ((float) screenHeight - scale
* (float) (image.getHeight())) / 2.0f;
}
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
canvas.save();
canvas.drawColor(0, Mode.CLEAR);
canvas.drawColor(Color.WHITE);
if(mode == DRAG || mode == NORMAL) {
//This works perfectly as expected
canvas.translate(horizontalOffset, verticalOffset);
canvas.scale(scale, scale);
canvas.drawBitmap(image, getMatrix(), paint);
}
else if (mode == ZOOM) {
//PROBLEM AREA - when applying pinch zoom,
//the image jumps to a position abruptly
canvas.scale(scale, scale, touchX, touchY);
canvas.drawBitmap(image, getMatrix(), paint);
}
canvas.restore();
}
public class ScaleListener implements OnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float scaleFactorNew = detector.getScaleFactor();
if (detector.isInProgress()) {
touchX = detector.getFocusX();
touchY = detector.getFocusY();
scale *= scaleFactorNew;
invalidate(0, 0, screenWidth, screenHeight);
}
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
isScaling = true;
mode=ZOOM;
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
mode = NORMAL;
isScaling = false;
}
}
public class GestureListener implements GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener {
@Override
public boolean onDown(MotionEvent e) {
isScaling = false;
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
if (!isScaling) {
mode = DRAG;
isScaling = false;
horizontalOffset -= distanceX;
verticalOffset -= distanceY;
invalidate(0, 0, screenWidth, screenHeight);
} else {
mode = ZOOM;
isScaling = true;
}
return true;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
scaleGesture.onTouchEvent(event);
gestures.onTouchEvent(event);
return true;
}
}
Z góry dziękuję.