Android - Slow down zooming a custom view on Touch - android

I'm working on application where i implemented zoom feature but when i tries to pinch for zoom, it is being very fast zoom. How can i slow down or normalize this zoom feature ?
It's pleasure if any can help.
Here is the intialization of used variable in zooming
private static final float MIN_ZOOM = 1f;
private static final float MAX_ZOOM = 4f;
private float scaleAll = 1;
The code in OnTouchListener for zooming a view in my custom view is,
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
if (mode != MOVING_MODE) {
float[] v = new float[9];
matrix.getValues(v);
// translation
float mScalingFactor = v[Matrix.MSCALE_X];
RectF r = new RectF();
matrix.mapRect(r);
// mScalingFactor shall contain the scale/zoom factor
float scaledX = (x - r.left);
float scaledY = (y - r.top);
scaledX /= mScalingFactor;
scaledY /= mScalingFactor;
x = scaledX;
y = scaledY;
}
int maskedAction = event.getActionMasked();
switch (maskedAction) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
touchMode = DRAG;
if (mode == MOVING_MODE) {
DownPT.x = event.getX();
DownPT.y = event.getY();
}
invalidate();
break;
case MotionEvent.ACTION_MOVE:
if (touchMode == DRAG) {
if (mode == MOVING_MODE) {
PointF mv = new PointF(event.getX() - DownPT.x, event.getY() - DownPT.y);
matrix.postTranslate(mv.x, mv.y);
DownPT.x = event.getX();
DownPT.y = event.getY();
}
invalidate();
} else if (touchMode == ZOOM && mode == MOVING_MODE) {
// pinch zooming
float newDist = spacing(event);
if (newDist > 10f) {
scale = newDist / oldDist; //setting the scaling of the matrix...
// normalize scale
if (scale * scaleAll > MAX_ZOOM) {
scale = MAX_ZOOM / scaleAll;
}
if (scale * scaleAll < MIN_ZOOM) {
scale = MIN_ZOOM / scaleAll;
}
scaleAll *= scale;
//if scale > 1 means zoom in
// if scale < 1 means zoom out
matrix.postScale(scale, scale, mid.x, mid.y);
}
invalidate();
}
break;
case MotionEvent.ACTION_UP:
if (mode == ERASE_MODE || mode == UNERASE_MODE) {
touch_up();
is_from_init = false;
temt_x = event.getX();
temp_y = event.getY();
Log.d(TAG, "add to stack");
addToStack(false);
}
invalidate();
break;
case MotionEvent.ACTION_POINTER_UP: // second finger lifted
touchMode = NONE;
Log.d(TAG, "mode=NONE");
break;
case MotionEvent.ACTION_POINTER_DOWN: // first and second finger down
oldDist = spacing(event);
if (oldDist > 5f) {
savedMatrix.set(matrix);
midPoint(mid, event);
touchMode = ZOOM;
Log.d(TAG, "mode=ZOOM");
}
break;
}
return true;
}

Related

How to draw on image using finger when image zoom?

I am trying to develop draw something on image when image zoom in my project but when zoom then it will be create some offset between touch and drawing but without zoom it is working perfect. For example.
Code for image zoom:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.concat(matrix);
....
}
#Override
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = DRAG;
lastEvent = null;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
}
lastEvent = new float[4];
lastEvent[0] = event.getX(0);
lastEvent[1] = event.getX(1);
lastEvent[2] = event.getY(0);
lastEvent[3] = event.getY(1);
d = rotation(event);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
lastEvent = null;
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 && event.getPointerCount() == 2) {
float newDist = spacing(event);
matrix.set(savedMatrix);
if (newDist > 10f) {
float scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
if (lastEvent != null) {
float newRot = rotation(event);
float r = newRot - d;
matrix.postRotate(r, view.getMeasuredWidth() / 2, view.getMeasuredHeight() / 2);
}
}
break;
}
invalidate();
return true;
}
Code for drawing:
#Override
public boolean onTouch(View view, MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchStart(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touchMove(x, y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touchEnd();
invalidate();
break;
}
return true;
}
private void touchMove(float x, float y) {
float f1 = Math.abs(x - mX);
float f2 = Math.abs(y - mY);
if ((f1 >= 4.0F) || (f2 >= 4.0F)) {
path.quadTo(mX, mY,
(x + mX) / 2.0F,
(y + mY) / 2.0F);
mX = x;
mY = y;
}
}
private void touchStart(float x, float y) {
path.reset();
path.moveTo(x, y);
blurView.pathList.add(path);
blurView.strokeWidthList.add(strokeWidth);
mX = x;
mY = y;
}
private void touchEnd() {
path.lineTo(mX, mY);
path = new Path();
}
can any one help me for how to handle scale factor or how to remove image zoom scale factor into the finger touch.
You usually store the scale factor, and multiplies many of your coordinates handle system by its value.
Simply as that.

How to get right coordinates Zoom In on canvas or ImageView android

Basically I would like to draw lines on imageView when that image is zoomed.
The problem is that i dont know how to get right coordinates on touch event when Zoom In
Here is my code:
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
view.setScaleType(ImageView.ScaleType.MATRIX);
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: //first finger down only
savedMatrix.set(matrix);
if (draw) {
if (i == 1) {
startX = event.getX();
startY = event.getY();
i = 2;
} else if (i == 2) {
endX = event.getX();
endY = event.getY();
onDraw();
i = 3;
} else if (i == 3) {
startX = event.getX();
startY = event.getY();
onDraw();
i = 2;
}
} else {
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG");
mode = DRAG;
}
break;
case MotionEvent.ACTION_UP: //first finger lifted
case MotionEvent.ACTION_POINTER_UP: //second finger lifted
if (!draw) {
mode = NONE;
Log.d(TAG, "mode=NONE");
}
break;
case MotionEvent.ACTION_POINTER_DOWN: //second finger down
if (!draw) {
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
}
}
break;
case MotionEvent.ACTION_MOVE:
if (!draw) {
if (mode == DRAG) {
matrix.set(savedMatrix);
matrix.getValues(matrixValues);
matrixX = matrixValues[2];
matrixY = matrixValues[5];
width = matrixValues[0] * (view.getDrawable().getIntrinsicWidth());
height = matrixValues[4] * (view.getDrawable().getIntrinsicHeight());
dx = event.getX() - start.x;
dy = event.getY() - start.y;
//if image will go outside left bound
if (matrixX + dx > 0) {
dx = -matrixX;
}
//if image will go outside right bound
if (matrixX + dx + width < view.getWidth()) {
dx = view.getWidth() - matrixX - width;
}
//if image will go oustside top bound
if (matrixY + dy > 0) {
dy = -matrixY;
}
//if image will go outside bottom bound
if (matrixY + dy + height < view.getHeight()) {
dy = view.getHeight() - matrixY - height;
}
matrix.postTranslate(dx, dy);
}
break;
}
} //perform the transformation.
view.setImageMatrix(matrix);
return true; // indicate event was handled
}
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return (float) Math.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);
}
private void sizeScreen() {
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
screenHeight = displaymetrics.heightPixels;
screenWidth = displaymetrics.widthPixels;
}
Here is method for zoom
#Override
public void onClick(View v) { // Parameter v stands for the imageView that was clicked.
matrix.set(savedMatrix);
float[] values = new float[9];
matrix.getValues(values);
switch (v.getId()) {
case (R.id.bt_zoom_in):
if (!draw) {
scale = scale + 0.1f;
if (scale > MAX_ZOOM) {
scale = MAX_ZOOM;
} else if (scale < MIN_ZOOM) {
scale = MIN_ZOOM;
}
}
break;
case R.id.bt_zoom_out:
if (!draw) {
scale = scale - 0.1f;
if (scale > MAX_ZOOM) {
scale = MAX_ZOOM;
} else if (scale < MIN_ZOOM) {
scale = MIN_ZOOM;
}
//matrix.setScale(scale, scale, mid.x, mid.y);
//imageView.setImageMatrix(matrix);
}
break;
case R.id.bt_draw:
if (draw) {
draw = false;
bt_draw.setText("Draw");
} else {
draw = true;
bt_draw.setText("Finish");
}
break;
}
matrix.setScale(scale, scale, mid.x, mid.y);
imageView.setImageMatrix(matrix);
}
Here is method for draw
public void onDraw() {
Bitmap lineABmp = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
Bitmap lineAMutBmp = lineABmp.copy(Bitmap.Config.ARGB_8888, true);
Bitmap copy = Bitmap.createBitmap(lineAMutBmp);
Canvas c = new Canvas(copy);
Paint pnt = new Paint();
pnt.setColor(Color.rgb(27, 163, 156));
pnt.setStrokeWidth(7);
c.drawLine(startX, startY, endX, endY, pnt);
imageView.setImageBitmap(copy);
}
}
Finally do it using this link I used the answer by Andres
public boolean onTouch(View v, MotionEvent event) {
...
float []m = new float[9];
matrix.getValues(m);
float transX = m[Matrix.MTRANS_X] * -1;
float transY = m[Matrix.MTRANS_Y] * -1;
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: //first finger down only
savedMatrix.set(matrix);
if (draw) {
if (i == 1) {
startX = Math.abs((event.getX() + transX) / scale);
startY = Math.abs((event.getY() + transY) / scale);
i = 2;
} else if (i == 2) {
endX = Math.abs((event.getX() + transX) / scale);
endY = Math.abs((event.getY() + transY) / scale);
onDraw();
i = 3;
} else if (i == 3) {
startX = Math.abs((event.getX() + transX) / scale);
startY = Math.abs((event.getY() + transY) / scale);
onDraw();
i = 2;
}
} else {
..
}
break;
case MotionEvent.ACTION_UP: //first finger lifted
case MotionEvent.ACTION_POINTER_UP: //second finger lifted
...
break;
case MotionEvent.ACTION_POINTER_DOWN: //second finger down
...
break;
case MotionEvent.ACTION_MOVE:
...
break;
}
} //perform the transformation.
view.setImageMatrix(matrix);
return true; // indicate event was handled
}

ImageView limit drag and drop and zoom out of screen

I want to limit drag and drop of imageView to not goes out of screen, i don't know how do that, specially when imageView is zoomed, how can i keep imageView in the screen when it's zoomed or not?
here is my code:
/**
* Apply drag zoom to image
*
* #param imageToEdit
* #param mActivity
*/
public static void setOntoucheListner(ImageView imageToEdit, Activity mActivity, final ImageView imageMask) {
// Calcul pourcentage du min image
float ratio1 = imageToEdit.getWidth() / imageMask.getWidth();
float ratio2 = imageToEdit.getHeight() / imageMask.getHeight();
if (ratio1 < 1 && ratio2 < 1)
ZOOM_MIN = 1;
else
ZOOM_MIN = Math.min(ratio1, ratio2);
Display display = mActivity.getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
matrix = new Matrix();
savedMatrix = new Matrix();
startPoint = new PointF();
midPoint = new PointF();
// imageToEdit.setImageMatrix(new Matrix());
/** * set on touch listner on image */
imageToEdit.setOnTouchListener(new View.OnTouchListener() {
private float savedTranslateX = 0;
private float savedTranslateY = 0;
#Override
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
System.out.println("matrix=" + savedMatrix.toString());
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
startPoint.set(event.getX(), event.getY());
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(midPoint, event);
mode = ZOOM;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
imageMask.getTop();
imageMask.getTop();
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - startPoint.x, event.getY() - startPoint.y);
mode = DRAG;
} else if (mode == ZOOM) {
float newDist = spacing(event);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
matrix.postScale(scale, scale, midPoint.x, midPoint.y);
}
}
break;
}
float[] f = new float[9];
matrix.getValues(f);
float scaleX = f[Matrix.MSCALE_X];
float scaleY = f[Matrix.MSCALE_Y];
if (mode == ZOOM) {
if (scaleX <= ZOOM_MIN)
matrix.postScale((ZOOM_MIN) / scaleX, (ZOOM_MIN) / scaleY, midPoint.x, midPoint.y);
else if (scaleX >= ZOOM_MAX)
matrix.postScale((ZOOM_MAX) / scaleX, (ZOOM_MAX) / scaleY, midPoint.x, midPoint.y);
else {
view.setImageMatrix(matrix);
}
} else {
view.setImageMatrix(matrix);
}
return true;
}
#SuppressLint("FloatMath")
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);
}
});
}
}
Thank's a lot for your responses
I solved my problem, when user drap imageView out of bounds and release his fingers, i replace imageView on the last valid places so i complete case MotionEvent.ACTION_POINTER_UP like this: My limit here is not the screen but another ImageView,
case MotionEvent.ACTION_POINTER_UP:
matrix.getValues(values);
translateX = values[Matrix.MTRANS_X];
translateY = values[Matrix.MTRANS_Y];
Log.d("####### actualWidthImageToEdit"
+ actualWidthImageToEdit);
Log.d("####### translateX" + translateX);
Log.d("####### imageMask.getRight()" + imageMask.getRight());
// After User release fingers from screen we test if image
// is on a valid position if not we replace it in the last
// valid position
if (mode == DRAG || mode == DEZOOM) {
if (
// Limit Left, Move left to right
translateX > imageMask.getLeft()
// Limit Button, from top to buttom
|| translateY > imageMask.getTop()
// left to right
|| actualWidthImageToEdit
- imageMask.getRight() + translateX < 0
// Limit Top, from buttom to top
|| actualHeightImageToEdit
- imageMask.getBottom() + translateY < 0
) {
matrix = new Matrix(savedMatrix);
view.setImageMatrix(matrix);
view.invalidate();
}
}

Android ImageView zoom, rotate, position change prob

I am using a the following code for a image, which will rotate, zoom in-out with pinch. User can make its position by dragging it.
activity_img_match.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#drawable/brokenbone"
android:gravity="center_vertical|center_horizontal" >
<ImageView
android:id="#+id/bonestruct"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="matrix"
android:src="#drawable/bone" />
</FrameLayout>
ImgMatchActivity.java
public class ImgMatchActivity extends Activity implements OnTouchListener {
private static final String TAG = "Touch";
// These matrices will be used to move and zoom image
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
Matrix savedMatrix2 = new Matrix();
// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
private static final float MAX_ZOOM = 5.0f;
private static final float MIN_ZOOM = 0.15f;
int mode = NONE;
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_img_match);
ImageView bonestruct = (ImageView) findViewById(R.id.bonestruct);
bonestruct.setOnTouchListener(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_img_match, menu);
return true;
}
public boolean onTouch(View selectedView, MotionEvent event) {
// TODO Auto-generated method stub
ImageView view = (ImageView) selectedView;
int rotation = 25;
// Dump touch event to log
dumpEvent(event);
// Handle touch events here...
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:
mode = NONE;
Log.d(TAG, "mode=NONE");
savedMatrix.set(matrix);
//matrix.postRotate(90);
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);
fixing();
view.setImageMatrix(savedMatrix2);
return true; // indicate event was handled
}
public void fixing() {
float[] value = new float[9];
matrix.getValues(value);
float[] savedValue = new float[9];
savedMatrix.getValues(savedValue);
WindowManager mWinMgr = (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
int width = mWinMgr.getDefaultDisplay().getWidth();
int height = mWinMgr.getDefaultDisplay().getHeight();
Drawable d = this.getResources().getDrawable(R.drawable.bone);
if (d == null)
return;
int imageWidth = d.getIntrinsicWidth();
int imageHeight = d.getIntrinsicHeight();
int scaleWidth = (int) (imageWidth * value[0]);
int scaleHeight = (int) (imageHeight * value[4]);
// don't let the image go outside
if (value[2] > width - 1)
value[2] = width - 10;
else if (value[5] > height - 1)
value[5] = height - 10;
else if (value[2] < -(scaleWidth - 1))
value[2] = -(scaleWidth - 10);
else if (value[5] < -(scaleHeight - 1))
value[5] = -(scaleHeight - 10);
//Log.d("value[0]", "value[0]: "+value[0]);
//Log.d("value[4]", "value[4]: "+value[4]);
// maximum zoom ratio: MAX
if (value[0] > MAX_ZOOM || value[4] > MAX_ZOOM) {
value[0] = MAX_ZOOM;
value[4] = MAX_ZOOM;
// value[2] = savedValue[2];
// value[5] = savedValue[5];
}
// minimum zoom ratio: MIN
/*if (value[0] < MIN_ZOOM || value[4] < MIN_ZOOM) {
value[0] = MIN_ZOOM;
value[4] = MIN_ZOOM;
// value[2] = savedValue[2];
// value[5] = savedValue[5];
}*/
matrix.setValues(value);
savedMatrix2.set(matrix);
}
/** Show an event in the LogCat view, for debugging */
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());
}
/** Determine the space between the first two fingers */
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);
}
/** Calculate the mid point of the first two fingers */
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);
}
}
Now I can drag the image, zoom it-out by pinch action. But there is no rotation at all. How to get the rotation action and get rotation angle?
Try with below code its working for me.
float[] lastEvent = null;
float d = 0f;
float newRot = 0f;
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = DRAG;
lastEvent = null;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
}
lastEvent = new float[4];
lastEvent[0] = event.getX(0);
lastEvent[1] = event.getX(1);
lastEvent[2] = event.getY(0);
lastEvent[3] = event.getY(1);
d = rotation(event);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
lastEvent = null;
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 && event.getPointerCount() == 2) {
float newDist = spacing(event);
matrix.set(savedMatrix);
if (newDist > 10f) {
float scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
if (lastEvent != null) {
newRot = rotation(event);
float r = newRot - d;
matrix.postRotate(r, view.getMeasuredWidth() / 2,
view.getMeasuredHeight() / 2);
}
}
break;
}
view.setImageMatrix(matrix);
return true;
}
//For rotate image on multi-touch.
private float rotation(MotionEvent event) {
double delta_x = (event.getX(0) - event.getX(1));
double delta_y = (event.getY(0) - event.getY(1));
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}

How to keep an image inside the screen limits while using pinch zoom and drag gestures?

I'm building an app that uses the pinch zoom and drag. The problem is that for now I can drag the picture out of it bounds. I wanted to know how can I use drag and make sure the image stays on the screen at the same time.
Here is my code :
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView)v;
//handle touch events here.
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 temp = new Matrix();
temp.set(matrix);
temp.postScale(scale, scale, mid.x, mid.y);
float[] f = new float[9];
temp.getValues(f);
Float xScale = f[0];
if(xScale >= 1 && xScale <= 10){
matrix.postScale(scale, scale, mid.x, mid.y);
savedMatrixZoom.set(matrix);
}else{
matrix.set(savedMatrixZoom);
}
}
break;
}
} //perform the transformation.
view.setImageMatrix(matrix);
return true; // indicate event was handled
}
Why not grab the dimensions of the screen and check the MotionEvent coordinates are within these before updating your matrix?
Something like..
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int screenHight = displaymetrics.heightPixels;
int screenWidth = displaymetrics.widthPixels;
...
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
int newX = event.getX() - start.x;
int newY = event.getY() - start.y;
if ( (newX <= 0 || newX >= screenWidth) ||
(newY <= 0 || newY >= screenHeight) )
break;
matrix.set(savedMatrix);
matrix.postTranslate(newX, newY);
}
...
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int sH = displaymetrics.heightPixels;
int sW = displaymetrics.widthPixels;
float dx, dy, newX, newY;
switch (action) {
case MotionEvent.ACTION_DOWN:
dx = event.getRawX() - v.getX();
dy = event.getRawY() - v.getY();
break;
case MotionEvent.ACTION_MOVE:
newX = event.getRawX() - dx;
newY = event.getRawY() - dy;
if ((newX <= 0 || newX >= sW-v.getWidth()) || (newY <= 0 || newY >= sH-v.getHeight()))
break;
v.setX(newX);
v.setY(newY);
break;
default:
break;
}
return true;
}

Categories

Resources