Android multi-touch implementation to zoom in and out of the image of translation, inertia sliding and other functions _android

Source: Internet
Author: User
Tags gety

The article will be based on the original foundation to do some extended functions:

1. Inertial sliding of pictures
2. Picture scaling is less than the normal ratio, let go will automatically rebound into normal proportions
3. Picture shrink enlarge in the maximum proportion, let go will automatically rebound into the maximum proportion

To achieve the image zoom, pan, double-click the basic functions such as scaling code as follows, each line of code I have made a detailed comment

public class Zoomimageview extends ImageView implements Scalegesturedetector.onscalegesturelistener, View.ontouchlistener, viewtreeobserver.ongloballayoutlistener{/** * The monitoring of the shrinking drop potential * * Private scalegesturedetector MScale
 Gesturedetector;
 /** * Monitor gestures * * Private gesturedetector mgesturedetector;
 /** * The matrix of the zoom translation of the picture/private matrix Mscalematrix;
 /** * The first time the picture is loaded to adjust the picture scaling ratio, so that the picture is wide or high full screen * * * Private Boolean Mfirst;
 /** * Image of the initialization of the proportion of * * private float Minitscale;
 /** * Picture of the largest proportion of * * private float Mmaxscale;

 /** * Double-click the magnification of the picture * * Private float Mmidscale;

 /** * Whether is automatically enlarged or reduced * * Private Boolean Isautoscale;
 -----------------------------------------------/** * The number of previous touch points * * private int mlastpointercount;
 /** * can drag * * Private Boolean Iscandrag;
 /** * The last slide of the x and y coordinates * * private float MLASTX;
 private float mlasty;
 /** * Sliding Critical value * * Private int mtouchslop;
 /** * Whether to check the left and right border * * Private Boolean ischeckleftandright;
  /** * Check for upper and lower bounds* * Private Boolean Ischecktopandbottom;
 Public Zoomimageview {This (context, NULL, 0);
 Public Zoomimageview (context, AttributeSet attrs) {This (context, attrs, 0);
  Public Zoomimageview (context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr);
  Be sure to set the scaletype of the picture to the MATRIX type Setscaletype (Scaletype.matrix);
  Initialize the zoom gesture listener Mscalegesturedetector = new Scalegesturedetector (context,this);
  Initialize Matrix Mscalematrix = new matrices ();
  Setontouchlistener (this);
  Mtouchslop = Viewconfiguration.get (context). Getscaledtouchslop (); Initializes the gesture detector, listens for double click event Mgesturedetector = new Gesturedetector (context,new Gesturedetector.simpleongesturelistener () {@Ove
    Rride public boolean Ondoubletap (Motionevent e) {//If it is being scaled automatically, returns directly without processing if (Isautoscale) return true;
    Get the coordinates of the click float x = E.getx ();
    Float y = e.gety (); If the current picture's zoom value is less than the specified double-click scaling value if (Getscale () < Mmidscale) {//To automatically enlarge the post (newAutoscalerunnable (mmidscale,x,y));
    }else{//The current picture's zoom value is greater than the initial scaling value, the post automatically shrinks (new Autoscalerunnable (minitscale,x,y));
   return true;



 }
  }); /** * Called when view is added to window, earlier than Ongloballayout, so you can register the listener here/@Override protected void Onattachedtowindow () {Super
  . Onattachedtowindow ();
 Getviewtreeobserver (). Addongloballayoutlistener (this); /** * Called when view is removed from window, so you can remove the listener here/@Override protected void Ondetachedfromwindow () {Super.ondetachedfro
  Mwindow ();
 Getviewtreeobserver (). Removeglobalonlayoutlistener (this); /** * This method is called when the layout tree changes, and we can get the width and height of the control in this method/@Override public void Ongloballayout () {//) initialize the image only the first time it is loaded, with a
   Variable Mfirst control if (!mfirst) {Mfirst = true;
   Gets the width and height int width of the control = GetWidth ();
   int height = getheight ();
   Gets the picture loaded in the current ImageView drawable d = getdrawable ();
   if (d = = null) {//If there is no picture, return directly; //Get the current picture wide and high, the width and height of the picture is not necessarily equal to the width and height of the control//So we need to judge the width and height of the picture and the width and height of the control//to display the picture fully in the screen int dw = D.getIntrinsicwidth ();
   int dh = d.getintrinsicheight ();
   We define a temporary variable that determines the final scaling value of float scale = 1.0f, based on the ratio of the picture to the width of the control. 
    If the picture is wider than the width of the control, the picture height is less than the control height if (dw>width && dh 

To achieve the image reduction, the effect of letting go rebound

To achieve this function is very simple, we first add a mminscale as a reduced to the minimum value, we are designated as the initial ratio of 1/4

 /**
  * Minimum scaling ratio * *
 private float Mminscale;
Initialize in Ongloballayout

 @Override public
 void Ongloballayout () {
 ...
 The minimum scaling ratio is 1/4 times times
 mminscale = MINITSCALE/4;
 ...
 }
In Onscale, modify the following code

 @Override public
 boolean Onscale (Scalegesturedetector detector) {
 ...
  if ((Scalefactor > 1.0f && Scale * Scalefactor < Mmaxscale)
    | | Scalefactor < 1.0f && scale * Scalefactor > Mminscale) {

   //border control, if the current scale is multiplied by the scalefactor after the minimum scaling ratio
   //We do not allow any further narrowing
   if (scale * Scalefactor < Mminscale + 0.01f) {

    scalefactor = Mminscale/scale;
   }
 ...
 }

So we can zoom to a minimum of 1/4 of the size of the initialization ratio, and then we need to add a drop back to the initial size of the animation effect, and then we need to ontouch in the ACTION_UP to add the following code

 @Override Public
 Boolean Ontouch (View V, motionevent event) {
 ...
  Case MOTIONEVENT.ACTION_UP:
    //When the finger is raised, the Mlastpointercount is placed 0 and the slide
    mlastpointercount = 0 is stopped;
    If the current picture size is less than the initialization size if
    (Getscale () < Minitscale) {
     //is automatically magnified to the initialization size
     post (the new autoscalerunnable (Minitscale), GetWidth ()/2,getheight ()/2));
    break;
 ...
 }

Now let's look at the effect

When the picture is enlarged, the rebound effect is loosened.

This function is realized and the above function is basically consistent, we can first try to write their own.
In the same vein, we need to first define a mmaxoverscale as a value that can be enlarged to the maximum value.

/**
  * Maximum overflow value * *
 private float Mmaxoverscale;
Initialize in Ongloballayout

 @Override public
 void Ongloballayout () {
 ...
 Maximum overflow value of 5 times times the maximum, can be arbitrarily adjusted
 Mmaxoverscale = Mmaxscale * 5;
 ...
 }
In Onscale, modify the following code

 @Override public
 boolean Onscale (Scalegesturedetector detector) {
 ...
  if ((Scalefactor > 1.0f && Scale * Scalefactor < Mmaxoverscale)
    | | Scalefactor < 1.0f && SCA Le * scalefactor > Mminscale) {

   if (scale * scalefactor > Mmaxoverscale + 0.01f) {

    scalefactor = Mmaxoversca Le/scale;
   }
 ...
 }

So when we zoom to the maximum scale, we can continue to zoom in, and then we also need to add the ACTION_UP function in the Ontouch.

 Case MOTIONEVENT.ACTION_UP:
    //When the finger is raised, the Mlastpointercount is placed 0 and the slide
    mlastpointercount = 0 is stopped;
    If the current picture size is less than the initialization size if
    (Getscale () < Minitscale) {
     //is automatically magnified to the initialization size
     post (the new autoscalerunnable (Minitscale), GetWidth ()/2,getheight ()/2));
    If the current picture size is greater than the maximum if
    (Getscale () > Mmaxscale) {
     //is automatically reduced to
     the maximum post (the new autoscalerunnable (Mmaxscale), GetWidth ()/2,getheight ()/2));
    Break

And then we'll look at the effect

To achieve the inertia of the picture sliding

To achieve the inertia of the picture, we need to use Velocitytracker to help us detect a speed when our fingers leave the picture, and then call the Scroller fling method based on the speed and the position of the picture to calculate the coordinates of x and y in the inertia slip process.

 @Override public boolean Ontouch (View V, motionevent event) {... switch (event.getaction ()) {case Motionevent.ac
    Tion_down://initialization speed Detector Mvelocitytracker = Velocitytracker.obtain ();
    if (Mvelocitytracker!= null) {//Add the current event to the detector mvelocitytracker.addmovement (event);
     ///When the finger clicks to the picture again, stop the picture's inertia slip if (mflingrunnable!= null) {mflingrunnable.cancelfling ();
    mflingrunnable = null;
  }
    ...
  } ... case motionevent.action_move:.//If sliding if (Iscandrag) {if (getdrawable ()!= null) {if (mveloc
      Itytracker!= null) {//Add the current event to the detector mvelocitytracker.addmovement (event);
    }
      ...
    }
    ... case MOTIONEVENT.ACTION_UP://When the finger is raised, the Mlastpointercount is placed 0, and the sliding mlastpointercount = 0 is stopped; If the current picture size is less than the initialization size if (Getscale () < Minitscale) {//is automatically magnified to the initialization size post (new autoscalerunnable Minitscale,getwid
    Th ()/2,getheight ()/2)); //If the current picture size is greater than the maximum if (Getscale () > Mmaxscale) {//Auto Shrink to maximum post (new Autoscalerunnable (Mmaxscale,getwidth ()/2,getheight ()/2)); } if (Iscandrag) {//If you can currently slide if (mvelocitytracker!= null) {///Add the current event to the Inspector Mvelocitytracker.addmovemen
      T (event);
      Calculate the current Velocity mvelocitytracker.computecurrentvelocity (1000);
      Get current x direction velocity final Float VX = mvelocitytracker.getxvelocity ();
      The velocity of the current Y-direction is final float VY = mvelocitytracker.getyvelocity ();
      mflingrunnable = new Flingrunnable (GetContext ()); Call the Fling method, passing in the width of the control and the speed of the current x and Y axes///The minus of the Velocityx and velocityy required by VX and VY and scroller here is exactly the opposite/so pass in a negative Mflingrunna
      Ble.fling (GetWidth (), GetHeight (), (int)-vx, (int)-vy);
     Executes the Run Method post (mflingrunnable);
 }} break;
     Case Motionevent.action_cancel://Release Speed checker if (Mvelocitytracker!= null) {mvelocitytracker.recycle ();
    Mvelocitytracker = null;



} break; /** * Inertial sliding/Private class Flingrunnable implements runnable{private Scroller MscrollEr

  private int mcurrentx, mcurrenty;
  Public Flingrunnable {mscroller = new scroller (context);
  public void cancelfling () {mscroller.forcefinished (true); /** * This method is mainly from the Ontouch or get the current sliding horizontal and vertical speed * Call the Scroller.fling method, this method can automatically calculate the inertia sliding * x and y rate of change, according to this rate of change we can be flat on the picture */public void Fling (int viewwidth, int viewheight, int velocityx, int velocityy) {RECTF RECTF = Getm
   ATRIXRECTF ();
   if (RECTF = = null) {return;
   //STARTX is the final int startx = Math.Round (-rectf.left) of the X coordinate of the left edge of the current picture;
   Final int MinX, MaxX, Miny, Maxy;
    If the picture width is greater than the control width if (rectf.width () > Viewwidth) {//This is a sliding range [Minx,maxx], see below for details MinX = 0;
   MaxX = Math.Round (Rectf.width ()-viewwidth);
   }else{///If the picture width is less than the control width, sliding MinX = MaxX = StartX is not allowed;
   //If the picture height is greater than the height of the control, the same final int starty = Math.Round (-rectf.top);
    if (Rectf.height () > viewheight) {miny = 0;
   Maxy = Math.Round (Rectf.height ()-viewheight); }else{miny = Maxy = Starty;
   } mcurrentx = StartX;

   Mcurrenty = Starty; if (startx!= MaxX | | starty!= maxy) {//Call fling method, and then we can get the current x and Y coordinates by calling Getcurx and Getcury) The calculation of this coordinate is to simulate an inertia slip to calculate, I
   According to this change of X and Y can simulate//out of the image of the inertial sliding mscroller.fling (startx,starty,velocityx,velocityy,minx,maxx,miny,maxy);

 }

  }

About Startx,minx,maxx make an explanation


As we can see from the diagram, the current picture can slide an interval is the left out of that block, so MinX and MaxX represents the interval of the minimum and the maximum value, STARTX is the screen left edge of the coordinate value, we can imagine is startx in the interval [Minx,maxx] movement. The y-axis direction is the same.

Now let's look at the effect

This is the entire content of this article, I hope to learn more about Android software programming help.

Related Article

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.