Notepad for Android Project-----gesture zooming and dragging pictures

Source: Internet
Author: User
Tags gety

This article is your own study notes, welcome reprint, but please specify the source:http://blog.csdn.net/jesson20121020

The above section realizes the view picture and the recording function, in which looks the picture, may call the system Tukulai to view the picture, may also customize the activity to view the picture, today on the basis of the previous section, realizes the gesture to zoom and drag the picture.

Presumably everyone has used the system of library, browse the picture, you can enlarge or reduce the picture by gesture, rotate the picture, drag and drop the image and other functions, we also for the self-defined view of the activity of the image to increase the gesture zoom and drag the image function, the effect such as:

In the top four pictures, you can zoom in and out with gestures (multitouch).

This is mainly used for multi-touch, so we first need to know the difference between multipoint and single point.

Single finger operation process: action_down-action_move-actioin_up

Multi-finger operation process: action_down-action_pointer_down-action_move-action_pointer_up-action_up

the general implementation of the image scaling is using the matrix of the Postscale method, then through the gesture (multipoint) to scale the picture is certainly no exception, the difference is through the finger swipe to determine the scale and center position, as follows:

to scale a picture with gestures:
1. Set the ScaleType property of ImageView to Matrix.

Because the implementation of the image scaling to use the matrix, so this property is the premise, you can set the ImageView settings in the XML, android:scaletype= "Matrix", or in the Code set Imageview.setscaletype ( Scaletype.matrix)

2. Bind a touch listener to ImageView

Touch Event Img.setontouchlistener (new TouchEvent ());

3. Multi-finger zooming and dragging pictures in touch events

This is the core of this section, mainly to determine the type of motionevent, is a single finger or multiple fingers, can be obtained through the event.getactionmasked (), and set up three flags, respectively, to determine whether the current operation is drag, zoom or no operation, if it is dragged, You need to record the starting and ending positions of your finger, and then use the matrix's Posttranslate method to move the picture. If scaling, you need to calculate the scale and position of the picture scaling, when calculating the scale, you need to know the diameter of the multi-finger movement, the ratio of the number of fingers moved before and after the scale to get the zoom, and to calculate the position of the image zoom, just calculate the point of the finger before and after the movement of the midpoint.

4. Controlling the zoom ratio

In fact, the completion of the first 3 steps can be achieved through gestures to control the zoom and movement of the image, but you will find that, at this time, the image can be enlarged infinity, can also be reduced to infinity, and, regardless of whether the picture is in the magnification state, or shrinking state, will be with your fingers move to anywhere. This is obviously not in line with the actual use, so this needs to control the scale of the image, the main code is as follows:

Controls the zoom ratio private void Controlscale () {float values[] = new Float[9];matrix.getvalues (values); if (mode = = Zoom) {if (values[ 0] < Minscaler) Matrix.setscale (Minscaler, Minscaler), else if (Values[0] > Maxscaler) matrix.setscale (Maxscaler, Maxscaler);}}

5. Set the image center display

with the 4th step, you can control the magnification of the picture so that the picture has a maximum and minimum bloom ratio, and when the calculated scale is less than the minimum scale, the current zoom is set to the minimum scale, and when it is larger than the maximum scale, Sets the zoom scale for the current picture to the maximum scale.

However, there is a problem, that is, regardless of the image enlargement or shrinking state, will move with your finger, but in the actual process, we often need to zoom in the picture is in the center of the control position, that is, set the picture centered, the code is as follows:

   //Auto center centered protected Void Center () {Center (true,true);          } private void Center (Boolean horizontal, Boolean vertical) {matrix M = new Matrix ();          M.set (matrix);          RECTF rect = new RECTF (0, 0, bm.getwidth (), Bm.getheight ());          M.maprect (rect);          float height = rect.height ();          Float width = rect.width ();          Float deltax = 0, DeltaY = 0;  if (vertical) {int screenheight = Dm.heightpixels;              Cell phone screen resolution height//int screenheight = 400;              if (height < screenheight) {DeltaY = (screenheight-height)/2-rect.top;              }else if (Rect.top > 0) {deltay =-rect.top;              }else if (Rect.bottom < screenheight) {DeltaY = Screenheight-rect.bottom;             }} if (horizontal) { int screenwidth = Dm.widthpixels;              Phone screen resolution width//int screenwidth = 400;              if (Width < screenwidth) {DeltaX = (screenwidth-width)/2-rect.left;                  }else if (Rect.left > 0) {deltax =-rect.left;              }else if (Rect.right < screenwidth) {deltax = Screenwidth-rect.right;      }} matrix.posttranslate (DeltaX, DeltaY);   }
By centering it, the picture cannot be moved to another location when it is not full, and you can move the picture to see the different locations of the picture only if the picture is larger than the screen.

Basically, with these 5 steps, you can already achieve the function of image gesture (multipoint) zooming, and also can control the scale and center display of the picture. The entire code is given below:

public class Showpicture extends Activity {private ImageView img;private Bitmap bm;private displaymetrics DM; Private Matrix matrix = new Matrix ();p rivate matrix Savedmatrix = new Matrix ();p rivate PointF mid = new PointF ();p rivate P  ointf start = new PointF ();p rivate static int DRAG = 2;private static int ZOOM = 1;private static int NONE = 0;private int mode = 0;private float olddist = 1f;private static float Minscaler = 0.3f;private static float Maxscaler = 3.0f; @Override protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Requestwindowfeature ( Window.feature_custom_title); Setcontentview (r.layout.activity_show_picture); GetWindow (). Setfeatureint ( Window.feature_custom_title, R.layout.title_add);//Set caption TextView Tv_title = (TextView) Findviewbyid (r.id.tv_title); Tv_title.settext ("View Picture"); Button Bt_back = (button) Findviewbyid (r.id.bt_back); Bt_back.setonclicklistener (new Onclicklistener () {@ overridepublic void OnClick (View arg0) {ShowPicture.this.finish ();}}); BuTton Bt_del = (Button) Findviewbyid (R.id.bt_save); Bt_del.setbackgroundresource (r.drawable.paint_icon_delete);d m =          New Displaymetrics (); Getwindowmanager (). Getdefaultdisplay (). Getmetrics (DM); Get the resolution IMG = (ImageView) Findviewbyid (r.id.iv_showpic); Intent Intent = This.getintent (); String Imgpath = Intent.getstringextra ("Imgpath"); bm = Bitmapfactory.decodefile (Imgpath);// Set Center display Savedmatrix.settranslate ((Dm.widthpixels-bm.getwidth ())/2, (Dm.heightpixels-bm.getheight ())/2); Img.setimagematrix (Savedmatrix);//Bind Picture Img.setimagebitmap (BM);//Touch Event Img.setontouchlistener (new TouchEvent ());} Add touch events to achieve picture gesture Zoom class TouchEvent implements ontouchlistener{@Overridepublic Boolean OnTouch (view view, motionevent Event) {switch (event.getactionmasked ()) {//click Touch, to drag case MotionEvent.ACTION_DOWN:matrix.set (Img.getimagematrix ())   ;   Savedmatrix.set (matrix);   Start.set (Event.getx (), event.gety ());   mode = DRAG; break;//multi-Touch, press case MotionEvent.ACTION_POINTER_DOWN:oldDist = getspacing (event); Savedmatrix.set (matrix); Getmidpoint (mid,event); mode = zoom;break;//multi-touch, lift 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);} Scaling else if (mode = = ZOOM) {//Get multi-fingered moving diameter, if greater than 10, is considered a zoom gesture float newdist = getspacing (event); if (Newdist >) {matrix.set ( Savedmatrix); float scale = Newdist/olddist;matrix.postscale (scale, SCALE,MID.X,MID.Y);}} break;} Img.setimagematrix (matrix); Controlscale ();//setcenter (); center (); return true;}} Distance private float getspacing (motionevent event) {float x = event.getx (0)-event.getx (1); Float y = event.gety (0)-EVENT.G Ety (1); return floatmath.sqrt (x * x + y * y);} Find the midpoint private void Getmidpoint (PointF mid,motionevent event) {float x = event.getx (0) + event.getx (1); Float y = event.gety (0 ) + event.gety (1); Mid.set (X/2, Y/2);} Control scaling private void Controlscale () {float values[] = new Float[9];matrix.getvalues (values); if (mode = = ZOOM) {if (Values[0] < Minscaler) Matrix.setscale (Minscaler, minscaler); else if (values[0] > Maxscaler) Matrix.setscale (Maxscaler, Maxscaler);}}      Center protected Void Center () {Center (true,true) with Auto center around and up and down;          } private void Center (Boolean horizontal, Boolean vertical) {matrix M = new Matrix ();          M.set (matrix);          RECTF rect = new RECTF (0, 0, bm.getwidth (), Bm.getheight ());          M.maprect (rect);          float height = rect.height ();          Float width = rect.width ();          Float deltax = 0, DeltaY = 0;  if (vertical) {int screenheight = Dm.heightpixels;              Cell phone screen resolution height//int screenheight = 400;              if (height < screenheight) {DeltaY = (screenheight-height)/2-rect.top;              }else if (Rect.top > 0) {deltay =-rect.top;           }else if (Rect.bottom < screenheight) {       DeltaY = Screenheight-rect.bottom;  }} if (horizontal) {int screenwidth = Dm.widthpixels;              Phone screen resolution width//int screenwidth = 400;              if (Width < screenwidth) {DeltaX = (screenwidth-width)/2-rect.left;                  }else if (Rect.left > 0) {deltax =-rect.left;              }else if (Rect.right < screenwidth) {deltax = Screenwidth-rect.right;      }} matrix.posttranslate (DeltaX, DeltaY); }  }

Note:

Another problem is that the initial center of the image problem, in the ImageView can be set property android:scaletype= "Fitcenter" to achieve the center of the picture display, but here is to achieve the gesture zoom picture, so need Set this property to Android:scaletype= "Matrix", but at the same time, this also poses a problem, that is, at the beginning, the picture cannot be centered.

the first way to find a solution online is to set ImageView's ScaleType property to Fitcenter in the XML file, and then set Setontouchlistener before the ImageView setscal () method. EType (Scaletype.matrix); But this method I did not succeed, the picture initially or in the upper left corner, the other way is to calculate the phone screen height and width, to the image center point (x, Y), and then through the matrix translation to that position, and finally through the Setimagematrix () Binds the matrix to ImageView to achieve an initial center display of the image. and I finally adopted the second method, the code is as follows:

Private displaymetrics DM;  ... dm = new Displaymetrics ();  Getwindowmanager (). Getdefaultdisplay (). Getmetrics (DM); Get resolution .../  /Set Center display savedmatrix.settranslate ((Dm.widthpixels-bm.getwidth ())/2, (Dm.heightpixels- Bm.getheight ())/2); Img.setimagematrix (Savedmatrix);

If you have a better way to make the image initially centered, please share.


Notepad for Android Project-----gesture zooming and dragging pictures

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.