Hi I’m trying to create an application where you can zoom and pan around a campus site map. I have that working but have run into problems restricting how much you can pan and zoom.I need help setting panning and zooming boundaries.
Any help would be greatly appreciated,
Thanks in advance
Here’s the code.
package com.scott;
import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageView;
public class Touch extends Activity implements OnTouchListener,OnClickListener {
private static final String TAG = "Touch";
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.touch);
ImageView view = (ImageView) findViewById(R.id.imageView);
view.setOnTouchListener(this);
Button buttonClose =(Button)findViewById(R.id.buttonClose);
buttonClose.setOnClickListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
dumpEvent(event);
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG");
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM");
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
Log.d(TAG, "mode=NONE");
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
// ...
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x,
event.getY() - start.y);
}
else if (mode == ZOOM) {
float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
view.setImageMatrix(matrix);
return true;
}
private void dumpEvent(MotionEvent event) {
String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
"POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
StringBuilder sb = new StringBuilder();
int action = event.getAction();
int actionCode = action & MotionEvent.ACTION_MASK;
sb.append("event ACTION_").append(names[actionCode]);
if (actionCode == MotionEvent.ACTION_POINTER_DOWN
|| actionCode == MotionEvent.ACTION_POINTER_UP) {
sb.append("(pid ").append(
action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
sb.append(")");
}
sb.append("[");
for (int i = 0; i < event.getPointerCount(); i++) {
sb.append("#").append(i);
sb.append("(pid ").append(event.getPointerId(i));
sb.append(")=").append((int) event.getX(i));
sb.append(",").append((int) event.getY(i));
if (i + 1 < event.getPointerCount())
sb.append(";");
}
sb.append("]");
Log.d(TAG, sb.toString());
}
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);
}
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
@Override
public void onClick(View src) {
switch(src.getId()){
case R.id.buttonClose:
finish();
break;
}
}
}
Well you could probably use this to adjust with postTranslate, this method should be called after youre own postScale and postTranslate
private void adjustPan(){
float[] matrixValues = new float[9];
matrix.getValues(matrixValues);
float currentY = matrixValues[Matrix.MTRANS_Y];
float currentX = matrixValues[Matrix.MTRANS_X];
float currentScale = matrixValues[Matrix.MSCALE_X];
float currentHeight = bitmap.getHeight() * currentScale;
float currentWidth = bitmap.getWidth() * currentScale;
float newX = currentX;
float newY = currentY;
RectF drawingRect = new RectF(newX, newY, newX + currentWidth,
newY + currentHeight);
float diffUp = Math.min(displayRect.bottom - drawingRect.bottom,
displayRect.top - drawingRect.top);
float diffDown = Math.max(displayRect.bottom - drawingRect.bottom,
displayRect.top - drawingRect.top);
float diffLeft = Math.min(displayRect.left - drawingRect.left,
displayRect.right - drawingRect.right);
float diffRight = Math.max(displayRect.left - drawingRect.left,
displayRect.right - drawingRect.right);
float x = 0, y = 0;
if (diffUp > 0)
y += diffUp;
if (diffDown < 0)
y += diffDown;
if (diffLeft > 0)
x += diffLeft;
if (diffRight < 0)
x += diffRight;
if(currentWidth < displayRect.width())
x = -currentX + (displayRect.width() - currentWidth) / 2;
if(currentHeight<displayRect.height())
y = -currentY + (displayRect.height() - currentHeight) / 2;
matrix.postTranslate(x, y);
}
where displayRect is a RectF that should look something like this:
displayRect = new RectF();
displayRect.set(0, 0, displaywidth, displayheight);
As for youre max min zoom you would need something like this before youre postScale:
float[] f = new float[9];
matrix.getValues(f);
float currentScale = f[Matrix.MSCALE_X];
if (scale * currentScale > maxZoom)
scale = maxZoom / currentScale;
else if (scale * currentScale < minZoom)
scale = minZoom / currentScale;
where minZoom is:
minZoom = Math.min(displayRect.width()/bitmap.getWidth(), displayRect.height()/bitmap.getHeight());
and maxZoom is what you like it to be.
Hope this was somewhat helpful.
(Original taken from somewhere, can't find link now tho)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With