Android realizes gesture sliding multi-point touch zoom panning Image effect _android

Source: Internet
Author: User

Now in the app, the picture preview function must be indispensable, the user has basically formed conditioned reflex, see Small map, click to see big picture, see big figure two fingers begin to enlarge, enlarge, begin to move to the designated part.
I. Overview
want to do picture support multi-touch, free to zoom, translation, need to know a few knowledge points: Matrix, Gesturedetector, scalegesturedetector and event distribution mechanism, PS: Will not do, you do not understand.
1. Matrix
Matrix, look at the depth of the 3-dimensional matrix of the multiply ah what, strange trouble ~ ~
In fact, so understand the line:
Matrix
Data Structure : 3-D matrix;
Internal storage:new float[9]; The interior is a one-dimensional array with 9 elements inside; can be initialized with setvalues (float[] values)
Each element represents the meaning:

{ 
    mscale_x, mskew_x, Mtrans_x, mskew_y, mscale_y, mtrans_y, Mpersp_0, mpersp_1,  
        mpersp_2  
};  

Literally, you should be able to see which represents the X-direction scaling, which represents the vertical offset bar ~ ~ There are 3 not know, nothing, please disregard.
Operation
Like you want to set the matrix offset to 200,100
You can write this:

Matrix Transmatrix = new Matrix (); 
    Float[] values = new float[] {1.0, 0, 0, 1.0, 0, 0, 1.0}; 
    Transmatrix.setvalues (values); 

If you need to rotate 30 degrees, enlarge twice times ~ ~
That's a really weird thing to write about.
The matrix provides some common APIs: for example, we can write this:

Matrix Transmatrix = new Matrix (); 
    

How to get a value:
Of course, we have a variety of operations on a matrix, a postscale, a posttranslate; so now how to get the current zoom ratio:
Said Setvalues can initialize, then getvalues can get the value of the current matrix, get a one-dimensional array, 9 elements, and then the corresponding value by subscript.
Like I want to know now scaling in x direction:

Public final float Getscale () 
  { 
    scalematrix.getvalues (matrixvalues); 
    return matrixvalues[matrix.mscale_x]; 
  

OK, I know this is enough ~ ~
2, Gesturedetector
Well, look at the API, you can capture the long press, double-click what; usage will be in the example
3, Scalegesturedetector
Well, it's kind of like inheriting, actually not, a standalone class ~ used to detect scaling gestures ~ ~ Usage will be in the example
Second, actual combat
For everyone better understanding, I will be independent of each function, and finally integrated together ~ ~ Also on the use of each API to learn.
1, free scaling
Requirements: When a picture is loaded, center the picture on the screen, the picture is wider or higher than the screen, and the image is reduced to the screen size; The
code is not very long, Directly attached to the code

Package Com.zhy.view; 
Import Android.content.Context; 
Import Android.graphics.Matrix; 
Import android.graphics.drawable.Drawable; 
Import Android.util.AttributeSet; 
Import Android.util.Log; 
Import android.view.MotionEvent; 
Import Android.view.ScaleGestureDetector; 
Import Android.view.ScaleGestureDetector.OnScaleGestureListener; 
Import Android.view.View; 
Import Android.view.View.OnTouchListener; 
Import Android.view.ViewTreeObserver; 
 
Import Android.widget.ImageView; public class Zoomimageview extends ImageView implements Onscalegesturelistener, Ontouchlistener, Viewtreeobserver.ong 
   
  Loballayoutlistener {private static final String TAG = ZoomImageView.class.getSimpleName (); 
  public static final Float Scale_max = 4.0f; 
 
  /** * When initializing the scaling ratio, if the picture is wider or higher than the screen, this value will be less than 0 * * Private float Initscale = 1.0f; 
 
  /** * 9 values for storing the matrix * * Private final float[] matrixvalues = new FLOAT[9]; 
 
  Private Boolean once = true; /** * Zoom gesture Detection * * PrivaTe scalegesturedetector mscalegesturedetector = null; 
 
  Private final Matrix Mscalematrix = new Matrix (); 
  Public Zoomimageview {This (context, NULL); 
    Public Zoomimageview (context, AttributeSet attrs) {Super (context, attrs); 
    Super.setscaletype (Scaletype.matrix); 
    Mscalegesturedetector = new Scalegesturedetector (context, this); 
  This.setontouchlistener (this); 
    @Override public boolean Onscale (Scalegesturedetector detector) {Float scale = Getscale (); 
 
    float scalefactor = Detector.getscalefactor (); 
 
    if (getdrawable () = null) return true; /** * Zoom Range Control */if (Scale < Scale_max && scalefactor > 1.0f) | | 
    (Scale > Initscale && scalefactor < 1.0f)) {/** * Maximum minimum value/if (Scalefactor * Scale < Initscale) {scalefactor = 
      Initscale/scale; } if (Scalefactor* scale > Scale_max) {scalefactor = Scale_max/scale; 
          /** * Set ZOOM ratio * * Mscalematrix.postscale (Scalefactor, Scalefactor, GetWidth ()/2, 
      GetHeight ()/2); 
    Setimagematrix (Mscalematrix); 
 
  return true; 
  @Override public boolean Onscalebegin (Scalegesturedetector detector) {return true; @Override public void Onscaleend (Scalegesturedetector detector) {} @Override public boolean Ontou 
 
  CH (View V, motionevent event) {return mscalegesturedetector.ontouchevent (event); /** * Get Current Scaling * * @return/public final float Getscale () {Mscalematrix.getvalue 
    S (matrixvalues); 
  return matrixvalues[matrix.mscale_x]; 
    } @Override protected void Onattachedtowindow () {Super.onattachedtowindow (); 
  Getviewtreeobserver (). Addongloballayoutlistener (this); } @SuppressWarnings ("deprecation") @OVerride protected void Ondetachedfromwindow () {Super.ondetachedfromwindow (); 
  Getviewtreeobserver (). Removeglobalonlayoutlistener (this); 
      @Override public void Ongloballayout () {if (once) {drawable d = getdrawable (); 
      if (d = = null) return; 
      LOG.E (TAG, d.getintrinsicwidth () + "," + d.getintrinsicheight ()); 
      int width = getwidth (); 
      int height = getheight (); 
      Get picture width and height int dw = d.getintrinsicwidth (); 
      int dh = d.getintrinsicheight (); 
      float scale = 1.0f;  If the picture is wider or taller than the screen, zoom to the screen wide or high if (DW > Width && dh <= height) {scale = width * 1.0f/ 
      Dw 
      } if (dh > Height && DW <= width) {scale = height * 1.0F/DH; //If the width and height are greater than the screen, let it fit proportionally to the screen size if (DW > Width && dh > height) {scale = MATH.MI 
      N (DW * 1.0f/width, DH * 1.0f/height); } inItscale = scale; 
      The picture moves to the screen center Mscalematrix.posttranslate ((WIDTH-DW)/2, (HEIGHT-DH)/2); 
      Mscalematrix. Postscale (scale, scale, getwidth ()/2, GetHeight ()/2); 
      Setimagematrix (Mscalematrix); 
    once = false; 
 } 
 
  } 
 
}

1, we in the ongloballayout callback, according to the picture width and height and the screen width and height, the picture is scaled and moved to the center of the screen. If the picture is very small, then the normal display, do not enlarge the ~
2), we let Ontouchlistener motionevent hand over to scalegesturedetector for processing

@Override Public 
  Boolean Ontouch (View v., motionevent event) 
  {return 
    mscalegesturedetector.ontouchevent ( event); 
 
  

3, in the Onscale callback in the Image Zoom control, first to zoom range of the judgment, and then set Mscalematrix scale value
Now the effect:
1, less than the width and height of the screen

2, larger than the width and height of the screen

But, however, there are problems:

    • 1, zoom center point, we set is fixed, the middle of the screen
    • 2, enlarge, cannot move

Below, we first solve the problem of scaling center point, not always press the center of the screen, like me, I am more concerned about the eyes of the sister, I want to enlarge that piece ~ ~ ~
2. Set Zoom Center
1, the Simple setting Zoom Center
Just set the center is simple, directly modify the lower center point:

/** 
       * Set ZOOM ratio * * 
      Mscalematrix.postscale (scalefactor, Scalefactor, 
          detector.getfocusx (), Detector.getfocusx ()); 
      Setimagematrix (Mscalematrix); 

However, the arbitrary center point of magnification, narrowing, will lead to changes in the location of the picture, resulting in a picture wider than the screen, the picture and screen appear white side; the picture is less than the screen, but not centered.
2, control the zoom when the picture display range
So we need to manually control the range when zooming:

/** * In zoom, the picture display range of control/private void Checkborderandcenterwhenscale () {RECTF rect = GETMATRIXRECTF 
    (); 
    float deltax = 0; 
 
    float DeltaY = 0; 
    int width = getwidth (); 
 
    int height = getheight (); If the width or height is greater than the screen, the control range if (Rect.width () >= width) {if (Rect.left > 0) {deltax =-rect 
      . Left; 
      } if (Rect.right < width) {deltax = Width-rect.right; 
      } if (Rect.height () >= height) {if (Rect.top > 0) {deltay =-rect.top; 
      } if (Rect.bottom < height) {deltay = Height-rect.bottom;  If width or height is less than screen, let it Center if (rect.width () < width) {deltax = width * 0.5f-rect.right + 0.5f 
    * Rect.width (); 
    } if (Rect.height () < height) {deltay = height * 0.5f-rect.bottom + 0.5f * rect.height (); LOG.E (TAG, "deltax =" + DeltaX + ", DeltaY = "+ DeltaY); 
 
  Mscalematrix.posttranslate (DeltaX, DeltaY);  /** * To get a range of pictures based on the matrix of the current picture * * @return * * Private RECTF GETMATRIXRECTF () {Matrix matrix 
    = Mscalematrix; 
    RECTF rect = new RECTF (); 
    drawable d = getdrawable (); 
      if (null!= d) {rect.set (0, 0, d.getintrinsicwidth (), D.getintrinsicheight ()); 
    Matrix.maprect (rect); 
  return rect; 
 }

Inside the Onscale remember to call:

/** 
       * Set ZOOM ratio * * 
      Mscalematrix.postscale (scalefactor, Scalefactor, 
          detector.getfocusx (), Detector.getfocusy ()); 
      Checkborderandcenterwhenscale (); 
      Setimagematrix (Mscalematrix); 

This is good, can be free to enlarge any place, and will not appear on the edge of White edge, but also good to let the picture displayed in the middle of the screen (when the picture is wider or higher than the screen);
3. Post the layout file

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android" 
  xmlns:tools= "http:// Schemas.android.com/tools " 
  android:layout_width=" match_parent " 
  android:layout_height=" Match_parent " > 
 
  <com.zhy.view.zoomimageview 
    android:layout_width= "fill_parent" 
    android:layout_height= " Fill_parent " 
    android:scaletype=" Matrix " 
    android:src=" @drawable/xx "/> 
 
</RelativeLayout> 

The eyes are the window of the mind, let's enlarge and see, the effect chart:

Well, to this picture of our random way to reduce ~ ~ ~ ~ ~ ~ ~ ~ if only need to zoom function, you can take it to use ~
For space reasons, the next article will continue to refine this view:
1. Increase the number of touch control when moving
2, increase double-click to become larger, double click to Small
3. Event-conflict issues when using with Viewpager

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.