I have two images inside my layout. I need to zoom that image which i touched. We know that Frame can display a single view at a time. So how do i perform zoom on each imageview separately ? My xml file :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="#+id/imageView1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:src="#drawable/image1" />
<ImageView
android:id="#+id/imageView2"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center" android:src="#drawable/image2"
/>
</FrameLayout>
Activity file :
public class MyActivity extends Activity implements OnTouchListener
{
private static final String TAG = "Touch";
// These matrices will be used to scale points of the image
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
// The 3 states (events) which the user is trying to perform
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
// these PointF objects are used to record the point(s) the user is touching
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
private ImageView iv1;
private ImageView iv2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
iv1 = ((ImageView)findViewById(R.id.imageView1));
iv1.setOnTouchListener(this);
iv2 = ((ImageView)findViewById(R.id.imageView2));
iv2.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()) {
case R.id.imageView1:
zoomImageView(v, event);
break;
case R.id.imageView2:
zoomImageView(v, event);
break;
default:
break;
}
return true;
}
private boolean zoomImageView(View v, MotionEvent event) {
ImageView view = (ImageView) v;
view.setScaleType(ImageView.ScaleType.MATRIX);
float scale;
switch (event.getAction() & 255)
{
case MotionEvent.ACTION_DOWN: // first finger down only
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG"); // write to LogCat
mode = DRAG;
break;
case MotionEvent.ACTION_UP: // first finger lifted
case 6: // second finger lifted
mode = NONE;
Log.d(TAG, "mode=NONE");
break;
case 5: // first and second finger down
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 5f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM");
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG)
{
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY() - start.y); // create the transformation in the matrix of points
}
else if (mode == ZOOM)
{
// pinch zooming
float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 5f)
{
matrix.set(savedMatrix);
scale = newDist / oldDist; // setting the scaling of the
// matrix...if scale > 1 means
// zoom in...if scale < 1 means
// zoom out
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
view.setImageMatrix(matrix); // display the transformation on screen
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 FloatMath.sqrt(x * x + y * y);
}
/*
* --------------------------------------------------------------------------
* Method: midPoint Parameters: PointF object, MotionEvent Returns: void
* Description: calculates the midpoint between the 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'am able zoom only image1 which is on top. How do i get the zoom functionality for bottom image on touch of image2 ? I should be able to zoom the image on which i touched. Please help me.
You can use LinearLayout and align them horizontally or vertically in this way you will have two imageviews which are independent with each other
then use gestureimageview which supports panning zooming and and double tap see link below....
hope this answers your question :D
Click here!
https://github.com/jasonpolites/gesture-imageview
Use ZoomageView instead of ImageView.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.jsibbold.zoomage.ZoomageView
android:id="#+id/imageView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:src="#drawable/image1" />
<com.jsibbold.zoomage.ZoomageView
android:id="#+id/imageView2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:src="#drawable/image2" />
</FrameLayout>
Add dependencies :
implementation 'com.jsibbold:zoomage:1.1.0'
Hope this will help you.
Related
I was able to use a class created by one of the StackOverflow users for my needs.
The class was working fine, but It did not include scrolling(vertically, horizontally). I modified the following class by including the code under MotionEvent.Action_Up , which now provides scrolling both horizontally and vertically. The main problem I am having is with the ZOOM mode.
If you look closely, Zoom mode happens on MotionEvent.ACTION_POINTER_DOWN:
The logic is that it calculates the distance between two fingers and figures out the midpoint between them on the midpoint method. The center of the Zoom must be this midpoint. The code under MotionEvent.ACTION_POINTER_DOWN takes care of
saving and scaling the matrix.
This class is an ImageView and it hosts a drawable graph. The graph draws nicely and the horizontal and vertical scrolling are now enabled, but the zoom is causing problems: When the drawable loads and I try zooming it works fine, but if I try scrolling after that, the drawable gets lost in the view. Likewise, when I scroll at first and then Zoom, the drawable gets lost in the view very fast. It seems like the matrix changes the ImageView coordinates and therefore the midpoint is not the one that I need as the origin of the zoom.
Inside the drawable class onDraw() I implement the following logic:
canvas.save();
GraphImage.translateX = GraphImage.translateX + MainActivity.keeper14;
GraphImage.translateY = GraphImage.translateY + MainActivity.keeper15;
canvas.translate(GraphImage.translateX, GraphImage.translateY);
canvas.scale(GraphImage.main_scale, GraphImage.main_scale, MainActivity.middy.x , MainActivity.middy.y);
//do my draw calls here
MainActivity.keeper14 = GraphImage.translateX;
MainActivity.keeper15 = GraphImage.translateY;
canvas.restore();
As you can see, I use values updated inside the ImageView onTouch method.
I think the problem might be that the matrix is not coordinating well with the
canvas.scale() and canvas.translate() calls.
Here is the ImageView class. By the way, what is the purpose of the matrix in this class. Does it work only on the ImageView or also on the drawable that it has? Also, I use a scaleType = Matrix for this view.
public class GraphImage extends android.support.v7.widget.AppCompatImageView {
Paint paint;
Context c;
int color;
Matrix matrix;
Matrix savedMatrix;
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
static PointF start,mid;
float oldDist;
static float main_scale;
static float translateX,translateY;
String savedItemClicked;
String TAG = "Batman";
float mx , my, curX, curY;
public GraphImage(Context context, AttributeSet attrs) {
super(context,attrs);
//all the variables are init here
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
dumpEvent(event);
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
mx = event.getX();
my = event.getY();
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(MainActivity.middy, event);
mode = ZOOM;
Log.d(TAG, "mode=ZOOM");
}
break;
case MotionEvent.ACTION_UP:
curX = event.getX();
curY = event.getY();
matrix.set(savedMatrix);
matrix.postTranslate(curX - mx, curY - my);
translateX = curX - mx;//event.getX() - start.x;
translateY = curY - my;//event.getY() - start.y;
this.invalidateDrawable(this.getDrawable());
break;
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);
translateX = event.getX() - start.x;
translateY = event.getY() - start.y;
this.invalidateDrawable(this.getDrawable());
*/
} else
if (mode == ZOOM) {
float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
main_scale = scale;
matrix.postScale(scale, scale, MainActivity.middy.x, MainActivity.middy.y);
this.invalidateDrawable(this.getDrawable());
}
}
break;
}
this.setImageMatrix(matrix);
//invalidate();
return true;
}
/** Determine the space between the first two fingers */
private float spacing(MotionEvent event) {
float x = event.getX(0) - event.getX(1);// Math.abs(event.getX() - mx);//event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);//Math.abs(event.getY() - my);//event.getY(0) - event.getY(1);
return (float)Math.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);//mx + event.getX();//event.getX(0) + event.getX(1);//
float y = event.getY(0) + event.getY(1);//my + event.getY();//event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
MainActivity.middy = point;
}
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());
}
}
Thanks for any suggestions
I added a few static variables on MainActivity class: translationXX, translationYY , drawing__scale.
Whenever ACTION_UP came up, I updated translationXX and translationYY, as such:
translationXX = translationXX + (curX - mx); //Likewise for translationYY
To coordinate with the changes that occurred whenever the drawable was invalidated:
canvas.translate(MainActivity.translationXX , MainActivity.translationYY);// inside onDraw of the drawable
Likewise, for zoom: Instead of MainActivity.middy as the midpoint of the finger placement on the screen that signified a zoom gesture, I went back to the variable static "mid" defined on GraphImage class. It happened that Mainactivity.middy kept the
old values assigned to it when the mode was ZOOM. Therefore, the zoom was really not doing good things. Inside the method midpoint of the GraphImage class I replaced the following line:
MainActivity.middy = point;
with the line:
mid = point;
To coordinate the zoom changes that took place inside GraphImage, inside my drawable class onDraw method I scaled the canvas, as such:
canvas.scale(MainActivity.drawing_scale, MainActivity.drawing_scale, GraphImage.mid.x,GraphImage.mid.y);//MainActivity.drawing_scale was updated when the mode was ZOOM inside the onTouch method of GraphImage
Also, inside ACTION_POINTER_UP: I had to invalidate the drawable since without this
the drawable would zoom as ACTION_MOVE was being called but then, it went back to its previous non-zoom state as soon as the fingers stopped touching the screen.
inside ACTION_POINTER_UP:
MainActivity.middy = mid; //this line was called on ACTION_MOVE when the mode = ZOOM
matrix.postScale(MainActivity.drawing_scale, MainActivity.drawing_scale,MainActivity.middy.x,MainActivity.middy.y)//middy was updated with the latest midpoint "mid" on a previous called to ZOOM inside ACTION_MOVE
After this line we simply call invalidate on the drawable. Also, I created a Boolean called moveit = false inside the onTouch(). Whenever ZOOM mode was on, moveit = true
Whenever ACTION_UP was called it would excute the code needed for the translation of the drawable only if(!moveit){//code that translates drawable}
This changes provide an acceptable view that zooms and scrolls in all directions. I might need to use the onFling() of the GestureDetector class to make it feel more realistic but it works very well. I avoided the nested scrolling (vertical and horizontal). But, I still will like to learn more about the details on using a matrix.
I am having issue here with imageView touch. I have two imageview inside a FrameLayout. Consider both images are rectangle and overlap to each other.
Image 1 is touchable, draggable and movable
Image 2 is not movable
When I touch the Image 1 area, it will move correctly. However, when I touch Image 2 area which is overlap between Image 1, it cause the Image 1 to move. I have try to detect touch by Id and Tag but it is still saying I am touching Image 1
I want to prevent/restrict Image 1 from moving when touching Image 2 overlap area. How can I achieve this? Image 2 can be a custom shape, view or canvas also.
I am putting in XML
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/frm"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_weight="1" >
<ImageView
android:id="#+id/imgTest1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="matrix"
android:tag="img1"
android:src="#drawable/a">
</ImageView>
<ImageView
android:id="#+id/imgTest2"
android:layout_width="100dp"
android:layout_height="100dp"
android:scaleType="matrix"
android:tag="img2"
android:src="#drawable/b">
</ImageView>
</FrameLayout>
</LinearLayout>
Image 1 touch event
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (v.getTag() != null && v.getTag().equals("img1")) {
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;
}
else
return false;
}
});
Thank you.
I believe the problem is here:
if (v.getTag() != null && v.getTag().equals("img1")) {
ImageView view = (ImageView) v;
You are checking if the tag of the view is equal to img1 and then do your work. However I can't see anywhere that you are checking if the view is equal to img2 (as stated in your xml).
You should add this after you are finished with your above if statement and do the appropriate work inside it:
else if (v.getTag() != null && v.getTag().equals("img2")) {
//do work here
}
In my application i want to get image x and y coordinates after drag and zoom the image. So I am using the following code.In my xml i have taken relative layout.This is relative layout.
<RelativeLayout
android:id="#+id/image"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#+id/buttonlayout"
android:layout_marginTop="0dp" >
</RelativeLayout>
In this relative layout i want to drag the image and zoom the image.So that's why I have created Image view programatically and apply the touch listener to that image view.This is the oncreate code.
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.inventory_submit_images_activity);
relImage=(RelativeLayout) findViewById(R.id.image);
imgMarker = new ImageView(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT);
params.leftMargin = 0;
params.topMargin = 0;
relImage.addView(imgMarker, params);
imgMarker.setScaleType(ImageView.ScaleType.MATRIX);
bmdragImage=BitmapFactory.decodeResource(getResources(), R.drawable.image_marker);
height = bmdragImage.getHeight();
width = bmdragImage.getWidth();
imgMarker.setImageBitmap(bmdragImage);
imgMarker.setOnTouchListener(this);
}
And this is the ontouch method and related methods.
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
ImageView view = (ImageView) v;
view.setScaleType(ImageView.ScaleType.MATRIX);
float scale = 0;
layoutParamss = (RelativeLayout.LayoutParams)
v.getLayoutParams();
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: // first finger down only
x=(int) event.getX();
y=(int) event.getY();
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG"); // write to LogCat
mode1 = DRAG1;
break;
case MotionEvent.ACTION_UP: // first finger lifted
x_cordinate=(int) event.getX();
y_cordinate=(int) event.getY();
Log.e("x_cordinate==",""+x_cordinate+" "+bmdragImage.getHeight());
Log.e("y_cordinate==",""+y_cordinate+" "+bmdragImage.getWidth());
break;
case MotionEvent.ACTION_POINTER_UP: // second finger lifted
mode1 = NONE1;
Log.d(TAG, "mode1=NONE1");
break;
case MotionEvent.ACTION_POINTER_DOWN: //second finger down..
oldDist = spacing(event);
Log.d(TAG, "oldDist=" + oldDist);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode1 = ZOOM1;
Log.d(TAG, "mode=ZOOM" );
}
break;
case MotionEvent.ACTION_MOVE:
Log.e("ACTION_MOVE","ACTION_MOVE");
if (mode1 == DRAG1){
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY() - start.y); // create the transformation in the matrix of points
}
else if (mode1 == ZOOM1){
// pinch zooming
float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 5f){
matrix.set(savedMatrix);
scale = newDist / oldDist; // setting the scaling of the image..
matrix.postScale(scale, scale, mid.x, mid.y);
height=(int) (bmdragImage.getHeight()*scale);
width=(int) (bmdragImage.getWidth()*scale);
Log.e("height int===="+scale,""+height);
Log.e("width int====="+scale,""+width);
}
}
break;
}
view.setImageMatrix(matrix); // display the transformation on screen
return true; // indicate event was handled
}
/** 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);
}
This code is dragging and zooming is working fine. But my problem is getting x coordinate and y coordinate after drag the image.These x and y values are getting wrong. Because where ever i touch the image with in the relative layout, dragging is working.Because of these code in oncreate of image view params. So x and y values are getting wrong.
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT,
RelativeLayout.LayoutParams.FILL_PARENT);
If i change the image layout params to wrap contnet like the bellow,the image dragging is with in that area only. And zooming also not working properly. But my requirement is drag the image total relative layout.And get the x and y coordinates of image view.
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
Suggestions are appreciated..
I need to implement zooming, panning and then reset the ImageView to original scale/location. I use view.setImageMatrix(matrix) to perform zooming and moving in FrameLayout. Works perfectly so far. To restore to original layout, I tried to save the original matrix and reset to it, It doesn't work and I am kinda stuck. Appreciate any suggestions or tips!
The following are my current code:
a ViewPager contains fragments per Image
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
The fragment contains ImageView
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="#+id/ivPage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:scaleType="matrix"
android:src="#drawable/catalogue_test" />
</FrameLayout>
The java code does the zooming and panning work just fine, that actually was original from a tutorial page:
#Override
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
Log.d(tag, "ACTION_DOWN");
isDoubleTap = false;
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(tag, "mode=DRAG");
mode = DRAG;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
Log.d(tag, "ACTION_POINTER_UP");
mode = NONE;
Log.d(tag, "mode=NONE");
break;
case MotionEvent.ACTION_MOVE:
Log.d(tag, "ACTION_MOVE");
if (mode == DRAG) {
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY() - start.y);
} else if (mode == ZOOM) {
double newDist = spacing(event);
Log.d(tag, "newDist=" + newDist);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = (float) (newDist / oldDist);
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
if(isDoubleTap == false) {
view.setImageMatrix(matrix);
Log.d(tag, String.format("(%d, %d) - scale(%f, %f) xy(%f, %f)", view.getTop(), view.getLeft(), view.getScaleX(), view.getScaleY(), view.getX(), view.getY()));
}
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;
}
gestureDetector.onTouchEvent(event);
return true; // indicate event was handled
}
I didn't have any luck with the setImageMatrix(new Matrix()) method, but setting the scale type then resetting it worked.
setScaleType(ScaleType.CENTER_CROP);
setScaleType(ScaleType.MATRIX);
I know this is old but here is my answer.
1-)get startedMatrix of imageView onCreate method
2-)and changed ACTION_POINTER and ACTION_POINTER_UP method to these
--- case MotionEvent.ACTION_UP: // first finger lifted
mode = NONE;
break;
case MotionEvent.ACTION_POINTER_UP:// second finger lifted
fingerLifted();
matrix.set(startedMatrix);
view.setScaleType(ImageView.ScaleType.MATRIX);
mode = NONE;
Log.d(TAG, "mode=NONE");
break;
I hope this will help.
Isn't the original imageView Matrix simply an identity matrix?
imageView.setImageMatrix(new Matrix()); -- this will be a matrix with no translations/scales/etc aka the default/original matrix
Based on my research...
to reset ImageView to original Scale/Position
try this very simple code... just put this
setCotentView(R.layout.activity_image);
This will reset your ImageView from the start :) and it will work.
'm developing an application in which I'm pasting images, doing drawing and painting on canvas. This app can also Scale up/down the canvas or drag it to different location. My problem is: I can't get the correct canvas coordinates after scaling or dragging the canvas. I want to draw finger paint after the canvas is scaled or dragged but unable to retrieve the right place where i've touched...
#Override
public boolean onTouchEvent(MotionEvent event) {
scaleListener.onTouchEvent(event);
synchronized(thread.getSurfaceHolder()){
switch ( event.getAction() & MotionEvent.ACTION_MASK ){
case MotionEvent.ACTION_DOWN :
// Remember our initial down event location.
savedMatrix.set(m_matrix);
start.set(event.getX() , event.getY());
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN :
oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(m_matrix);
m_matrix.getValues(matrixValues);
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 && isDragAllowd){
m_matrix.set(savedMatrix);
rebound(event.getX() , event.getY());
}
else if(mode==ZOOM){
float newDist = spacing(event);
if (newDist > 10f){
m_matrix.set(savedMatrix);
float scale = newDist/oldDist;
m_matrix.getValues(matrixValues);
float currentScale = matrixValues[Matrix.MSCALE_X];
// limit zoom
if (scale * currentScale > maxZoom){
scale = maxZoom / currentScale;
//scale = maxZoom;
}
else if (scale * currentScale < minZoom){
scale = minZoom / currentScale;
//scale = minZoom;
}
m_matrix.postScale(scale, scale, mid.x, mid.y);
m_matrix.getValues(matrixValues);
}
}
break;
}
return true; //done with this event so consume it
}
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(currentBitmap, m_matrix, null);
c2.drawColor(Color.BLACK);
commandManager.executeAll(c2); // Drawing all the Paints on Canvas c2
// Overlay bitmap it's a transparent layour
canvas.drawBitmap(overlayBitmap, 0, 0, pTouch);
}
when user zoom the bitmap he is not able to draw over it , after zooming drawing doesn't happen at proper place.
use the following equation for transformed the points, after that user will not face an any difficulty painting during zoom or after scrolling.
float f1 = (( motionEvent.getX() - m_transformedPoints[0] )/( m_transformedPoints[2] - m_transformedPoints[0] ))*currentBitmapWidth;
float f2 = (( motionEvent.getY() - m_transformedPoints[1] )/( m_transformedPoints[3] - m_transformedPoints[1] ))*currentBitmapHeight;
//calculate the transformed view in onDraw Method
this.m_transformedPoints[0] = 0.0F;
this.m_transformedPoints[1] = 0.0F;
this.m_transformedPoints[2] = currentBitmapWidth;
this.m_transformedPoints[3] = currentBitmapHeight;
this.m_matrix.mapPoints(this.m_transformedPoints);