Rotate, Translate and and Zoom dynamically created image view in Android - android

Its may be repeated question but i didn't get any perfect clue or answer to my question.
I am trying to drag and drop images from one view to another, and trying to apply operation like translate,zoom and rotate image view on finger touch.
I went through most of the links for the same but all I getting is image get translate, zoom and rotate within image Matrix i.e. Image get rotate within its image view.
Problem is want to re size my image view too with image. I solved this problem for translate and zoom but I am getting stuck while doing for rotation.
Following is my code.
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: //first finger down only
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);
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: //first finger lifted
delete.setImageResource(R.drawable.delete);
mode = NONE;
case MotionEvent.ACTION_POINTER_UP: //second finger lifted
mode = NONE;
Log.d(TAG, "mode=NONE");
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
delete.setImageResource(R.drawable.share);
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY()- start.y);
float[] matrixValues = new float[9];
matrix.getValues(matrixValues);
float TransX = matrixValues[Matrix.MTRANS_X];
float TransY = matrixValues[Matrix.MTRANS_Y];
draggedImg.setX(draggedImg.getX()+TransX);
draggedImg.setY(draggedImg.getY()+TransY);
draggedImg.setPivotX(draggedImg.getX()+TransX+draggedImg.getWidth()/2);
draggedImg.setPivotY(draggedImg.getY()+TransY-draggedImg.getHeight()/2);
} else if (mode == ZOOM && event.getPointerCount() == 2) {
Log.d(TAG, "In Zoom Mode");
float newDist = spacing(event);
matrix.set(savedMatrix);
if (newDist > 10f) {
Drawable drawing = draggedImg.getDrawable();
Bitmap bitmap = ((BitmapDrawable)drawing).getBitmap();
scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
float[] matrixValues = new float[9];
matrix.getValues(matrixValues);
scaleX = matrixValues[Matrix.MSCALE_X];
scaleY = matrixValues[Matrix.MSCALE_Y];
params.width = (int)(bitmap.getWidth()*scaleX);
params.height =(int)(bitmap.getHeight()*scaleY);
float TransX = matrixValues[Matrix.MTRANS_X];
float TransY = matrixValues[Matrix.MTRANS_Y];
draggedImg.setPivotX(mid.x);
draggedImg.setPivotY(mid.y);
draggedImg.setScaleType(ImageView.ScaleType.FIT_CENTER);
draggedImg.setImageMatrix(matrix);
draggedImg.setLayoutParams(params);
}
if (lastEvent != null) {
Drawable drawing = draggedImg.getDrawable();
Bitmap bitmap = ((BitmapDrawable)drawing).getBitmap();
float newRot = rotation(event);
float r = newRot - d;
draggedImg.setScaleType(ImageView.ScaleType.MATRIX);
matrix.postRotate(r, v.getMeasuredWidth() / 2,v.getMeasuredHeight() / 2);
float[] matrixValues = new float[9];
matrix.getValues(matrixValues);
}
}
}
return true; // indicate event was handled
}
});

Please try MultiTouchLibrary . It will fulfill your need
This library provide you below functionality
Rotate
Scale Image (Pinch to zoom)

Related

Android - Slow down zooming a custom view on Touch

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;
}

Deleting ImageView by dragging to corner or over a button

I have one main and big ImageView and 4-5 small ImageView on it. The small ImageView can utilize zoom-in-out, drag to change place, and rotate, all by an onTouchEvent that I built in a custom ImageView.
Since use of onTouch event for dragging (moving) ImageView, I cant use OnDragListener for deleting the small ImageView. I want to delete by moving to corner of the screen or over a specific button.
Please help me find a solution.
public boolean onTouchEvent(MotionEvent event) {
this.setScaleType(ImageView.ScaleType.MATRIX);
float scale;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: //first finger down only
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d("amin", "mode=DRAG");
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: //first finger lifted
case MotionEvent.ACTION_POINTER_UP: //second finger lifted
mode = NONE;
Log.d("amin", "mode=NONE" );
break;
case MotionEvent.ACTION_MOVE:
if (mode == ZOOM && event.getPointerCount() == 2) {
float newDist = spacing(event);
matrix.set(savedMatrix);
if (newDist > 10f) {
scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
if (lastEvent != null) {
newRot = rotation(event);
float r = newRot - d;
matrix.postRotate(r, this.getMeasuredWidth() / 2,
this.getMeasuredHeight() / 2);
}
}else{
mode = DRAG;
// matrix.set(savedMatrix);
//matrix.postTranslate(event.getX() - start.x, event.getY()-start.y);
//this.layout((int)(start.x- (this.getWidth())),(int)(start.y- (this.getHeight())),(int) start.x, (int) start.y);
RelativeLayout.LayoutParams layoutPrarms = (RelativeLayout.LayoutParams)this.getLayoutParams();
int left = layoutPrarms.leftMargin + (int)(event.getX() - start.x);
int top = layoutPrarms.topMargin + (int)(event.getY() - start.y);
layoutPrarms.leftMargin = left;
layoutPrarms.topMargin = top;
this.setLayoutParams(layoutPrarms);
Log.d("amin", "mode=Drag" );
}
break;
}
// Perform the transformation
this.setImageMatrix(matrix);
return true;
}

How to move any image any time across same layout

My requirent is to generate multiple images dynamically and perform all operation on it like drag, drop, scale, rotate.I want every image can move on whole layout. but the problem is in which area 1 image can move another image can not move. I want user can any time select any image and any image can move any where in the layout.
My code to generate Image randomly inside onclick
LinearLayout.LayoutParams imParams = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
imge = new ImageView(MultiTouch.this);
imge.setImageResource(R.drawable.ic_launcher);
imge.setScaleType(ScaleType.MATRIX);
imge.buildDrawingCache();
BitmapDrawable drawable = (BitmapDrawable) imge.getDrawable();
Bitmap bitmap = drawable.getBitmap();
imge.setId(i++);
ll.addView(imge, imParams);
My ontouch listnner :
public boolean onTouch(View v, MotionEvent event) {
// Toast.makeText(MultiTouch.this, "onTouch", Toast.LENGTH_LONG).show();
ImageView view = (ImageView) v;
boolean defaultResult = v.onTouchEvent(event);
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = DRAG;
lastEvent = null;
System.out.println("ACTION_DOWN " );
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);
System.out.println("ACTION_POINTER_DOWN " );
break;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
lastEvent = null;
v.clearFocus();
System.out.println("ACTION_POINTER_UP " );
return false;
// break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
matrix.set(savedMatrix);
float dx = event.getX() - start.x;
float dy = event.getY() - start.y;
matrix.postTranslate(dx, dy);
} else if (mode == ZOOM) {
float newDist = spacing(event);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = (newDist / oldDist);
matrix.postScale(scale, scale, mid.x, mid.y);
}
if (lastEvent != null && event.getPointerCount() == 2) {
newRot = rotation(event);
float r = newRot - d;
float[] values = new float[9];
matrix.getValues(values);
float tx = values[2];
float ty = values[5];
float sx = values[0];
float xc = (view.getWidth() / 2) * sx;
float yc = (view.getHeight() / 2) * sx;
// matrix.postRotate(r, tx + xc, ty + yc);
matrix.postRotate(r, view.getWidth() / 2,
view.getHeight() / 2);
}
}
System.out.println("ACTION_MOVE " );
break;
default:
return defaultResult;
}
view.setImageMatrix(matrix);
return super.onTouchEvent(event);
}
and my xml code :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/frmlayut"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Button" />
<LinearLayout
android:id="#+id/ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/button1"
android:background="#drawable/backgrd"
android:orientation="vertical" >
</LinearLayout>
</RelativeLayout>
can any one tell me How to move any image any time across whole layout? Do i need to make layers, If yes how to do it.

How to determine scale factor in android

How to determine scale factor after zoom. I am using below code for pinch zoom. After zoom I have to draw circle on bitmap at correct location. I heard this the formula we have to use to draw at correct point after zoom.
Formula:
float x = ev.getX() / mScaleFactor + rect.left;
float y = ev.getY() / mScaleFactor + rect.top;
I have no idea how to calculate mScaleFactor.
I am using below code for pinch zoom,
public boolean onTouch(View v, MotionEvent rawEvent) {
WrapMotionEvent event = WrapMotionEvent.wrap(rawEvent);
// ...
ImageView view = (ImageView) v;
// 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:
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; // indicate event was handled
}
I am using imageview for displaying the image and zoom.
Using canvas and bitmap I am drawing the circle and setting to the image view after draw.
How to calculate scale factor for above pinch zoom code ?
Thanks in advance.
f you use the ScaleGestureDetector.SimpleOnScaleGestureListener class you can do something like this:
#Override
public boolean onScaleBegin(ScaleGestureDetector detector){
//the focal point before taking into account the zoom/translations/etc
float startX = detector.getFocusX();
float startY = detector.getFocusY();
initialPoints = new float[]{startX, startY};
if(transformMatrix.invert(inverseTransformMatrix))
inverseTransformMatrix.mapPoints(initialPoints );
//initialPoints now contain the correct points based on the current zoom
}

Getting coordinates and width/height from a matrix

I'm trying to make a media player for the Android platform and one of the features I'm trying to add is the ability to drag and pinch-zoom pictures.
The problem I'm having is I copied this code from "Hello, Android" ed. 3:
#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;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
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);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
view.setImageMatrix(matrix);
This code snippet does exactly what I want, but I need the pure X,Y coordinates and the width/height of the picture instead of the matrix.
Does anyone know how to change the matrix to X, Y coordinates and the width and height?
Turns out the solution is simple:
float[] values = new float[9];
matrix.getValues(values);
globalX = values[Matrix.MTRANS_X];
globalY = values[Matrix.MTRANS_Y];
width = values[Matrix.MSCALE_X]*imageWidth;
height = values[Matrix.MSCALE_Y]*imageHeight;
thanks, i've been looking all night to find this, only one thing:
in my example i had to use:
float height = matrixValues[4]*((ImageView)currentView).getDrawable().getIntrinsicHeight();
to get the correct height.
i wrote some methods which may help some users (thanks a lot for the code above!!!):
private void logImageViewMatrixInfos(Matrix matrix, ImageView imageView) {
float[] values = new float[9];
matrix.getValues(values);
float globalX = values[2];
float globalY = values[5];
float width = values[0]* imageView.getWidth();
float height = values[4] * imageView.getHeight();
Log.i("Log value", "Image Details: xPos: " + globalX + " yPos: " + globalY + "\nwidth: " + width + " height: " + height);
}
private float getXValueFromMatrix(Matrix matrix) {
float[] values = new float[9];
matrix.getValues(values);
float globalX = values[2];
return globalX;
}
private float getYValueFromMatrix(Matrix matrix) {
float[] values = new float[9];
matrix.getValues(values);
float globalY = values[5];
return globalY;
}
private float getWidthFromMatrix(Matrix matrix, ImageView imageview) {
float[] values = new float[9];
matrix.getValues(values);
float width = values[0]* imageview.getWidth();
return width;
}
private float getHeightFromMatrix(Matrix matrix, ImageView imageview) {
float[] values = new float[9];
matrix.getValues(values);
float height = values[4] * imageview.getHeight();
return height;
}
:=)

Categories

Resources