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.
Related
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;
}
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)
I am trying to create an app where user can touch an image and zoom using multi touch gesture. I searched over the net and found few solutions to do so. I even implemented those but all my efforts are in vain. First my code was not able to detect multitouch for which i realized that we also need to add MotionEvent.ACTION_MASK in switch case. Then now when i try to zoom the using multi touch no effect takes place. Please correct me.
TIA.
OnTouchListener onTouchListener = new OnTouchListener() {
int prevX,prevY;
float scale;
float mCurrentScale = 1.0f;
#Override
public boolean onTouch(View v, MotionEvent event) {
//view.setScaleType(ImageView.ScaleType.MATRIX);
scaleGestureDetector.onTouchEvent(event);
ImageView view = (ImageView) v;
v.bringToFront();
final RelativeLayout.LayoutParams par=(RelativeLayout.LayoutParams)v.getLayoutParams();
switch(event.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_UP:
par.topMargin+=(int)event.getRawY()-prevY;
par.leftMargin+=(int)event.getRawX()-prevX;
v.setLayoutParams(par);
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
lastEvent = null;
break;
case MotionEvent.ACTION_DOWN:
prevX=(int)event.getRawX();
prevY=(int)event.getRawY();
par.bottomMargin=-2*view.getHeight();
par.rightMargin=-2*view.getWidth();
v.setLayoutParams(par);
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d("hi","outside if DRAG");
mode = DRAG;
lastEvent = null;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDist = spacing(event);
Log.d("hi","Checking");
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_MOVE:
if(mode == DRAG){
par.topMargin+=(int)event.getRawY()-prevY;
prevY=(int)event.getRawY();
par.leftMargin+=(int)event.getRawX()-prevX;
prevX=(int)event.getRawX();
v.setLayoutParams(par);
}
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);
Log.e("hi", "TEsting");
}
if (lastEvent != null && event.getPointerCount() == 3) {
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 = (v.getWidth() / 2) * sx;
float yc = (v.getHeight() / 2) * sx;
matrix.postRotate(r, tx + xc, ty + yc);
}
}
break;
}
//ImageView view = (ImageView) v;
view.setImageMatrix(matrix);
v.invalidate();
return true;
}
};
You may need to use the piece of code:
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MultiTouchActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
TouchImageView img = new TouchImageView(this);
img.setImageResource(R.drawable.ice_age_2);
img.setMaxZoom(4f);
setContentView(img);
}
}
For reference use the link
here
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;
}
I am making application , In which I want to drag the image around the screen. Right now all thing is working fine , but if user keep swiping left to right the image would go far further into right. Which I do not want to do so .
What I want is that the image should not go out half of its width of bound. I mean image view should go only half out side of view/bound. I want it go half out side of bound in every coordinates I mean to left, right , top and bottom. It should not disappear. For this I am using touch listener. Right now I am capable of doing rotation , zooming and dragging (though its going out of bound)
So now i want it should not go out of bound , here is a code which I am using :
#Override
public boolean onTouch(View v, MotionEvent event) {
// ImageView view = (ImageView) v;
//view.setScaleType(ImageView.ScaleType.MATRIX);
float scale;
// Dump touch event to log
dumpEvent(event);
// Handle touch events here...
ImageView imageView = (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:
oldDistance = spacing(event);
if (oldDistance > 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) {
float newX = event.getX() - start.x;
float newY = event.getY() - start.y;
if ( newX <= 0-(imageView.getDrawable()
.getIntrinsicWidth() )){
Log.v("Bounds", "0-drawable width");
break;
}else if (newX >= screenWidth-(imageView.getDrawable()
.getIntrinsicWidth())){
Log.v("Bounds", "screen wdith-drawable width");
break;
}else if(newY <= 0-(imageView.getDrawable()
.getIntrinsicHeight())){
Log.v("Bounds", "Y 0-drawable width");
break;
}else if(newY >= (screenHeight-imageView.getDrawable()
.getIntrinsicHeight()) ) {
Log.v("Bounds", "y Screen-drawable width");
break;
}
matrix.set(savedMatrix);
matrix.postTranslate(newX, newY);
} else if (mode == ZOOM && event.getPointerCount() == 2) {
float newDistance = spacing(event);
if (newDistance > 10f) {
matrix.set(savedMatrix);
scale = newDistance / oldDistance;
float[] values = new float[9];
matrix.getValues(values);
float currentScale = values[Matrix.MSCALE_X];
if (scale * currentScale > MAX_ZOOM)
scale = MAX_ZOOM / currentScale;
else if (scale * currentScale < MIN_ZOOM)
scale = MIN_ZOOM / currentScale;
matrix.postScale(scale, scale, mid.x, mid.y);
}
if (lastEvent != null) {
newRot = rotation(event);
float r = newRot - d;
/* changes must be
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);
*/
float[] values = new float[9];
matrix.getValues(values);
float tx = values[2];
float ty = values[5];
float sx = values[0];
float xc = (imageView.getWidth() / 2) * sx;
float yc = (imageView.getHeight() / 2) * sx;
matrix.postRotate(r, tx + xc, ty + yc);
//I commented
matrix.postRotate(r, imageView.getMeasuredWidth() / 2,
imageView.getMeasuredHeight() / 2);
}
}
break;
}
imageView.setImageMatrix(matrix);
return true;
}
Eidt
and this is my XML
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/rl_capture">
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/fl_camera">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="content_desc_overlay"
android:src="#drawable/ic_launcher"
android:id="#+id/img_view"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/iv_overlay"
android:src="#drawable/groom01"
android:scaleType="matrix"
/>
</FrameLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="#+id/btn_screenshot"
android:layout_gravity="right|top"
/>
</RelativeLayout>
Hm. This is a little confusing. Is there some particular reason you're using intrinsicWidth/intrinsicHeight? These generally do not yield what I think you think they yield (see here). I assume your imageView is set up to have LayoutParams, and that your gravity isn't set so the origin of the image is at the top left. Here's what I'd do (not tested - tell me if there is an issue):
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
float newX = event.getX() - start.x;
float newY = event.getY() - start.y;
if ( newX < -imageView.getWidth()/2)){
Log.v("Bounds", "0-drawable width");
newX = -imageView.getWidth()/2;
}else if (newX > screenWidth-(imageView.getWidth()/2)){
Log.v("Bounds", "screen wdith-drawable width");
newX = screenWidth-(imageView.getWidth()/2);
}
// not else-if: consider the corners!
if(newY < -imageView.getHeight()/2){
Log.v("Bounds", "Y 0-drawable width");
newY = -imageView.getHeight()/2;
}else if(newY > (screenHeight-imageView.getHeight()/2) ) {
Log.v("Bounds", "y Screen-drawable width");
newY = screenHeight-imageView.getHeight()/2;
}
and so on.