Wednesday, December 7, 2011

Android ImageView: Zoom in Zoom out And Drag


Short about ImageView:
Android supports 3 common image formats PNG, JPG, GIF, along with 9 patch PNG images. Images are stored in the directory res/layout/drawable. As of version 1.6 of the Android SDK multiple drawable directories exist for different screen resolutions. There are low, medium, and high DPI specific directories, drawable-ldpi, drawable-mdpi, drawable-hdpi respectively. This allows you to create images at different DPI to enhance the appearance of your application. All image filenames should be lowercase and only contain letters, numbers, and underscores.
ImageView displays an arbitrary image, such as an icon. The ImageView class can load images from various sources (such as resources or content providers), takes care of computing its measurement from the image so that it can be used in any layout manager, and provides various display options such as scaling and tinting. Read more about ImageView from here
.

Step by Step Image zoom and drag example:
1. Create New Project (for example: touchmv)
2. Add image file (for example "butterfly.png") to "res/drawable/" folder
3. Edit res/layout/main.xml file as following
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/root"
   android:layout_width="match_parent"
   android:layout_height="match_parent">

 <ImageView android:id="@+id/imageView"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:src="@drawable/butterfly"
       android:scaleType="matrix"
       android:adjustViewBounds="true"
       android:layout_gravity="center">
    </ImageView>
    
</FrameLayout>
4. Create new class by name "Touch" as following:
package com.blogspot.vmustafayev4en.touchmv.listener;

import android.graphics.Matrix;
import android.graphics.PointF;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

public class Touch implements OnTouchListener {

 // These matrices will be used to move and zoom image
 Matrix matrix = new Matrix();
 Matrix savedMatrix = 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;
 int mode = NONE;

 // Remember some things for zooming
 PointF start = new PointF();
 PointF mid = new PointF();
 float oldDist = 1f;

 
 @Override
 public boolean onTouch(View v, MotionEvent event) {
  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());
   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);
  return true; // indicate event was handled
 }

 /** 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("]");
 }

 /** 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);
 }
}
5. Change your Activity class as following:
package com.blogspot.vmustafayev4en.touchmv;

import com.blogspot.vmustafayev4en.touchmv.listener.Touch;

import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;

public class BlogActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
      ImageView iv = (ImageView) findViewById(R.id.imageView);
      iv.setOnTouchListener(new Touch());
    }
}
If u done all steps then u'll be able drag image or zoom in zoom out it.

33 comments:

  1. This is one of the unique post.This is one of the challenging post.Nice to read about your post.
    Android app developer

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. The zooming and scrolling goes to infinite. Can we restrict that to some point?

    ReplyDelete
    Replies
    1. I am also facing the same problem. Zooming is going to infinite...how to restrict it.
      Also, I am trying to load the image on the Button Click event. The Touch method is being run but zooming of image is not happening. Please suggest how to implement the same on the button click even in a new screen.

      Delete
  4. May I please have the reply...

    ReplyDelete
  5. I have used this code in my android application https://play.google.com/store/apps/details?id=com.blogspot.vmustafayev4en.gdl
    In this program version not enough for u?

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. This comment has been removed by the author.

    ReplyDelete
  8. I'm wondering how you can limit the zoom. Like Sarma already said, to stop the infinity...also I would like to know how to center the image and zoom in a bit in default.

    ReplyDelete
    Replies
    1. And how do keep the image inside the viewscreen?

      Delete
    2. My Phone is Galaxy S II and android version is 2.3.3, may be why I have normal window in my application

      Delete
  9. can please explain me,how to zoom images in view flipper..??

    ReplyDelete
  10. good work Mr.Vasif, can you explain how this zooming can be implemented with more than 1 image in viewflipper?

    ReplyDelete
  11. These articles have got thorough discernment without unclear the readers.
    root android phone

    ReplyDelete
  12. Excellent, thank you very much, helped me a lot.

    Greetings from Colombia ....

    fanelmar

    ReplyDelete
  13. Thank you for this easy to follow tutorial.

    ReplyDelete
  14. ur post is very usefull thanks....
    have one doubt..can i use two imageviews for drag n zoom in ur coding??

    thanks in advance

    ReplyDelete
  15. Replies
    1. Yaaa..This is Really UseFull Dear....

      Delete
  16. very nice tutorial!

    thank you very much.

    Hassy

    ReplyDelete
  17. Sorry This is not working, send me full source file on hemant.katariya26@gmail.com

    ReplyDelete
  18. In the code of 5., you should put this code

    iv.setScaleType(ScaleType.MATRIX);

    then it works.

    ReplyDelete
  19. Thanks a lot for gr8 tutorial...

    ReplyDelete
  20. Just Awsmn Work Bro........Was Facing this problem from last many days..Thanks lot

    ReplyDelete
  21. I want to know if it possible to do zoom-in-zoom-out and drag with RelativeLayout???

    ReplyDelete
  22. Really good tutorial...it helped me a lot.
    Can please tell me how to rotate same image??

    ReplyDelete
  23. HI Please check below URL. Need your support.
    I need to create zoom and then able draw on zoom image part . i have done it but when i am saving image when its in zoom i just get image only zoom part which is display in device. Renaming all parts is missing.
    http://stackoverflow.com/questions/26924062/android-zoom-image-and-draw-line-on-image-with-current-zoom

    ReplyDelete
  24. Hi Vasif,
    It's very good one, but how to apply zoom & rotate for multiple images ?

    ReplyDelete