2015-11-23 13 views
7

Sto sviluppando un'applicazione Android per lo zoom dell'immagine, il trascinamento, la rotazione all'esterno del limite dello schermo. Per prima cosa devo adattare l'immagine a tutto lo schermo a livello di codice ed eseguire l'operazione di zoom, rotazione, trascinamento sull'immagine al di fuori del limite dello schermo. Ho usato il seguente codice, tutto funziona perfettamente quello che mi serve tranne che la funzione di rotazione. Ho confuso quel calcolo matriciale quindi per favore aiuta qualcuno a implementare la funzione di rotazione con questo codice.Implementare la rotazione della vista panoramica con il limite dello schermo nella classe sottostante

JavaCode:

import android.content.Context; 
import android.graphics.Bitmap; 
import android.graphics.Matrix; 
import android.graphics.PointF; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.view.ScaleGestureDetector; 
import android.view.View; 
import android.widget.ImageView; 

public class ZoomableImageView extends ImageView 
{ 
    Matrix matrix = new Matrix(); 

    static final int NONE = 0; 
    static final int DRAG = 1; 
    static final int ZOOM = 2; 
    static final int CLICK = 3; 
    int mode = NONE; 

    PointF last = new PointF(); 
    PointF start = new PointF(); 
    float minScale = 1f; 
    float maxScale = 4f; 
    float[] m; 

    float redundantXSpace, redundantYSpace; 
    float width, height; 
    float saveScale = 1f; 
    float right, bottom, origWidth, origHeight, bmWidth, bmHeight; 

    ScaleGestureDetector mScaleDetector; 
    Context context; 

    public ZoomableImageView(Context context, AttributeSet attr) 
    { 
     super(context, attr); 
     super.setClickable(true); 
     this.context = context; 
     mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
     matrix.setTranslate(1f, 1f); 
     m = new float[9]; 
     setImageMatrix(matrix); 
     setScaleType(ScaleType.MATRIX); 

     setOnTouchListener(new OnTouchListener() 
     { 

      @Override 
      public boolean onTouch(View v, MotionEvent event) 
      { 
       mScaleDetector.onTouchEvent(event); 

       matrix.getValues(m); 
       float x = m[Matrix.MTRANS_X]; 
       float y = m[Matrix.MTRANS_Y]; 
       PointF curr = new PointF(event.getX(), event.getY()); 

       switch (event.getAction()) 
       { 
        //when one finger is touching 
        //set the mode to DRAG 
        case MotionEvent.ACTION_DOWN: 
         last.set(event.getX(), event.getY()); 
         start.set(last); 
         mode = DRAG; 
         break; 
        //when two fingers are touching 
        //set the mode to ZOOM 
        case MotionEvent.ACTION_POINTER_DOWN: 
         last.set(event.getX(), event.getY()); 
         start.set(last); 
         mode = ZOOM; 
         break; 
        //when a finger moves 
        //If mode is applicable move image 
        case MotionEvent.ACTION_MOVE: 
         //if the mode is ZOOM or 
         //if the mode is DRAG and already zoomed 
         if (mode == ZOOM || (mode == DRAG && saveScale > minScale)) 
         { 
          float deltaX = curr.x - last.x;// x difference 
          float deltaY = curr.y - last.y;// y difference 
          float scaleWidth = Math.round(origWidth * saveScale);// width after applying current scale 
          float scaleHeight = Math.round(origHeight * saveScale);// height after applying current scale 
          //if scaleWidth is smaller than the views width 
          //in other words if the image width fits in the view 
          //limit left and right movement 
          if (scaleWidth < width) 
          { 
           deltaX = 0; 
           if (y + deltaY > 0) 
            deltaY = -y; 
           else if (y + deltaY < -bottom) 
            deltaY = -(y + bottom); 
          } 
          //if scaleHeight is smaller than the views height 
          //in other words if the image height fits in the view 
          //limit up and down movement 
          else if (scaleHeight < height) 
          { 
           deltaY = 0; 
           if (x + deltaX > 0) 
            deltaX = -x; 
           else if (x + deltaX < -right) 
            deltaX = -(x + right); 
          } 
          //if the image doesnt fit in the width or height 
          //limit both up and down and left and right 
          else 
          { 
           if (x + deltaX > 0) 
            deltaX = -x; 
           else if (x + deltaX < -right) 
            deltaX = -(x + right); 

           if (y + deltaY > 0) 
            deltaY = -y; 
           else if (y + deltaY < -bottom) 
            deltaY = -(y + bottom); 
          } 
          //move the image with the matrix 
          matrix.postTranslate(deltaX, deltaY); 
          //set the last touch location to the current 
          last.set(curr.x, curr.y); 
         } 
         break; 
        //first finger is lifted 
        case MotionEvent.ACTION_UP: 
         mode = NONE; 
         int xDiff = (int) Math.abs(curr.x - start.x); 
         int yDiff = (int) Math.abs(curr.y - start.y); 
         if (xDiff < CLICK && yDiff < CLICK) 
          performClick(); 
         break; 
        // second finger is lifted 
        case MotionEvent.ACTION_POINTER_UP: 
         mode = NONE; 
         break; 
       } 
       setImageMatrix(matrix); 
       invalidate(); 
       return true; 
      } 

     }); 
    } 

    @Override 
    public void setImageBitmap(Bitmap bm) 
    { 
     super.setImageBitmap(bm); 
     bmWidth = bm.getWidth(); 
     bmHeight = bm.getHeight(); 
    } 

    public void setMaxZoom(float x) 
    { 
     maxScale = x; 
    } 

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener 
    { 

     @Override 
     public boolean onScaleBegin(ScaleGestureDetector detector) 
     { 
      mode = ZOOM; 
      return true; 
     } 

     @Override 
     public boolean onScale(ScaleGestureDetector detector) 
     { 
      float mScaleFactor = detector.getScaleFactor(); 
      float origScale = saveScale; 
      saveScale *= mScaleFactor; 
      if (saveScale > maxScale) 
      { 
       saveScale = maxScale; 
       mScaleFactor = maxScale/origScale; 
      } 
      else if (saveScale < minScale) 
      { 
       saveScale = minScale; 
       mScaleFactor = minScale/origScale; 
      } 
      right = width * saveScale - width - (2 * redundantXSpace * saveScale); 
      bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); 
      if (origWidth * saveScale <= width || origHeight * saveScale <= height) 
      { 
       matrix.postScale(mScaleFactor, mScaleFactor, width/2, height/2); 
       if (mScaleFactor < 1) 
       { 
        matrix.getValues(m); 
        float x = m[Matrix.MTRANS_X]; 
        float y = m[Matrix.MTRANS_Y]; 
        if (mScaleFactor < 1) 
        { 
         if (Math.round(origWidth * saveScale) < width) 
         { 
          if (y < -bottom) 
           matrix.postTranslate(0, -(y + bottom)); 
          else if (y > 0) 
           matrix.postTranslate(0, -y); 
         } 
         else 
         { 
          if (x < -right) 
           matrix.postTranslate(-(x + right), 0); 
          else if (x > 0) 
           matrix.postTranslate(-x, 0); 
         } 
        } 
       } 
      } 
      else 
      { 
       matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY()); 
       matrix.getValues(m); 
       float x = m[Matrix.MTRANS_X]; 
       float y = m[Matrix.MTRANS_Y]; 
       if (mScaleFactor < 1) { 
        if (x < -right) 
         matrix.postTranslate(-(x + right), 0); 
        else if (x > 0) 
         matrix.postTranslate(-x, 0); 
        if (y < -bottom) 
         matrix.postTranslate(0, -(y + bottom)); 
        else if (y > 0) 
         matrix.postTranslate(0, -y); 
       } 
      } 
      return true; 
     } 
    } 

    @Override 
    protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) 
    { 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     width = MeasureSpec.getSize(widthMeasureSpec); 
     height = MeasureSpec.getSize(heightMeasureSpec); 
     //Fit to screen. 
     float scale; 
     float scaleX = width/bmWidth; 
     float scaleY = height/bmHeight; 
     scale = Math.min(scaleX, scaleY); 
     matrix.setScale(scale, scale); 
     setImageMatrix(matrix); 
     saveScale = 1f; 

     // Center the image 
     redundantYSpace = height - (scale * bmHeight) ; 
     redundantXSpace = width - (scale * bmWidth); 
     redundantYSpace /= 2; 
     redundantXSpace /= 2; 

     matrix.postTranslate(redundantXSpace, redundantYSpace); 

     origWidth = width - 2 * redundantXSpace; 
     origHeight = height - 2 * redundantYSpace; 
     right = width * saveScale - width - (2 * redundantXSpace * saveScale); 
     bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); 
     setImageMatrix(matrix); 
    } 
} 
+0

su qualsiasi angolo o solo angolo specifico si vuole ?? – curiousMind

+0

@Aashvi Ho bisogno di rotazione su qualsiasi angolo – Satheesh

risposta

3

si dovrebbe usare una matrice di farlo, come si sta già facendo, basta utilizzare il metodo postrotate.

Esempio:

Matrix matrix = new Matrix(); 
imageView.setScaleType(ImageView.ScaleType.MATRIX); 
matrix.postRotate((float) angle, pivotX, pivotY); 
imageView.setImageMatrix(matrix); 

Spero che questo aiuti.

+0

Per la rotazione questo codice funziona correttamente. Ho bisogno di applicare la rotazione per il mio codice di cui sopra senza affetto altre funzionalità come ingrandire, rimpicciolire, trascinare. Quindi, dove devo applicare questo codice. – Satheesh

+0

Dovresti usare la stessa matrice che usi per il ridimensionamento, basta chiamare postRotate quando vuoi ruotare. – Nanoc

+0

Ho bisogno di rotazione su qualsiasi angolo mentre l'utente usa con due dita. Dove devo applicare questo codice nel mio codice. – Satheesh

3

Basta aggiungere questo metodo nel codice di rotazione

public void rotateImage(int degrees, Bitmap mBitmap) { 
    if (mBitmap != null) { 
     Matrix matrix = new Matrix(); 
     matrix.postRotate(degrees); 
     Bitmap bitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight(), matrix, true); 
     setImageBitmap(bitmap); 

     mDegreesRotated += degrees; 
     mDegreesRotated = mDegreesRotated % 360; 
    } 
+0

Il codice sopra riportato funziona quando applichiamo i gradi. Ma ho bisogno di rotazione su qualsiasi angolo mentre l'utente usa due dita come il processo di zoom. Quindi gentilmente fammi sapere dove devo applicare il codice di rotazione in onTouchListener. – Satheesh

Problemi correlati