Android code to rotate an image view on touch or drag event

﹥>﹥吖頭↗ 提交于 2020-01-03 09:53:31

问题


I need to rotate an image on touch and drag. now i need a degree angle when user press the imageView and moove for rotating, kindly help me for the same.

imageView.setRotation(degree);

i need value of this degree variable in MotionEvent.ACTION_MOVE block.


回答1:


u want use the RotateGestureDetector in your project class as below given..

public class RotateGestureDetector extends TwoFingerGestureDetector {

/**
 * Listener which must be implemented which is used by RotateGestureDetector
 * to perform callbacks to any implementing class which is registered to a
 * RotateGestureDetector via the constructor.
 * 
 * @see RotateGestureDetector.SimpleOnRotateGestureListener
 */
public interface OnRotateGestureListener {
    public boolean onRotate(RotateGestureDetector detector);
    public boolean onRotateBegin(RotateGestureDetector detector);
    public void onRotateEnd(RotateGestureDetector detector);
}

/**
 * Helper class which may be extended and where the methods may be
 * implemented. This way it is not necessary to implement all methods
 * of OnRotateGestureListener.
 */
public static class SimpleOnRotateGestureListener implements OnRotateGestureListener {
    public boolean onRotate(RotateGestureDetector detector) {
        return false;
    }

    public boolean onRotateBegin(RotateGestureDetector detector) {
        return true;
    }

    public void onRotateEnd(RotateGestureDetector detector) {
        // Do nothing, overridden implementation may be used
    }
}


private final OnRotateGestureListener mListener;
private boolean mSloppyGesture;

public RotateGestureDetector(Context context, OnRotateGestureListener listener) {
    super(context);
    mListener = listener;
}

@Override
protected void handleStartProgressEvent(int actionCode, MotionEvent event){
    switch (actionCode) {
        case MotionEvent.ACTION_POINTER_DOWN:
            // At least the second finger is on screen now

            resetState(); // In case we missed an UP/CANCEL event
            mPrevEvent = MotionEvent.obtain(event);
            mTimeDelta = 0;

            updateStateByEvent(event);

            // See if we have a sloppy gesture
            mSloppyGesture = isSloppyGesture(event);
            if(!mSloppyGesture){
                // No, start gesture now
                mGestureInProgress = mListener.onRotateBegin(this);
            } 
            break;

        case MotionEvent.ACTION_MOVE:
            if (!mSloppyGesture) {
                break;
            }

            // See if we still have a sloppy gesture
            mSloppyGesture = isSloppyGesture(event);
            if(!mSloppyGesture){
                // No, start normal gesture now
                mGestureInProgress = mListener.onRotateBegin(this);
            }

            break;

        case MotionEvent.ACTION_POINTER_UP:
            if (!mSloppyGesture) {
                break;
            }

            break; 
    }
}


@Override
protected void handleInProgressEvent(int actionCode, MotionEvent event){    
    switch (actionCode) {
        case MotionEvent.ACTION_POINTER_UP:
            // Gesture ended but 
            updateStateByEvent(event);

            if (!mSloppyGesture) {
                mListener.onRotateEnd(this);
            }

            resetState();
            break;

        case MotionEvent.ACTION_CANCEL:
            if (!mSloppyGesture) {
                mListener.onRotateEnd(this);
            }

            resetState();
            break;

        case MotionEvent.ACTION_MOVE:
            updateStateByEvent(event);

            // Only accept the event if our relative pressure is within
            // a certain limit. This can help filter shaky data as a
            // finger is lifted.
            if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) {
                final boolean updatePrevious = mListener.onRotate(this);
                if (updatePrevious) {
                    mPrevEvent.recycle();
                    mPrevEvent = MotionEvent.obtain(event);
                }
            }
            break;
    }
}

@Override
protected void resetState() {
    super.resetState();
    mSloppyGesture = false;
}


/**
 * Return the rotation difference from the previous rotate event to the current
 * event. 
 * 
 * @return The current rotation //difference in degrees.
 */
public float getRotationDegreesDelta() {
    double diffRadians = Math.atan2(mPrevFingerDiffY, mPrevFingerDiffX) - Math.atan2(mCurrFingerDiffY, mCurrFingerDiffX);
    return (float) (diffRadians * 180 / Math.PI);
}
}

its easy to use the class and effective rotate in that.. i hope to useful....




回答2:


In order to move and zoom the image we’ll use a neat little feature on the ImageView class called matrix transformation. Using a matrix we can represent any kind of translation, rotation, or skew that we want to do to the image

// 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;

   @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) {
      }

      // Perform the transformation
      view.setImageMatrix(matrix);

      return true; // indicate event was handled
   }

And in the gesture

switch (event.getAction() & MotionEvent.ACTION_MASK) {
   case MotionEvent.ACTION_DOWN:
      savedMatrix.set(matrix);
      start.set(event.getX(), event.getY());
      Log.d(TAG, "mode=DRAG" );
      mode = DRAG;
      break;
   case MotionEvent.ACTION_UP:
   case MotionEvent.ACTION_POINTER_UP:
      mode = NONE;
      Log.d(TAG, "mode=NONE" );
      break;
   case MotionEvent.ACTION_MOVE:
      if (mode == DRAG) {
         matrix.set(savedMatrix);
         matrix.postTranslate(event.getX() - start.x,
         event.getY() - start.y);
      }
      break;
}

you need to play with Matrix class. here you can get the translate and using it you can get rotation angle. here is a tutorial for it.

After performing transformations such as rotation of a bitmap about an arbitrary point, the scale is lost. Of course, this makes sense because the bitmap is rotated inside the same bounds.

To get the real scale now, along with the most reliable degree of rotation, I had to follow this method. Hope it saves the rest of you a night or two.

you can get angle as follows :-

float[] v = new float[9];
matrix.getValues(v);
// translation is simple
float tx = v[Matrix.MTRANS_X];
float ty = v[Matrix.MTRANS_Y];

// calculate real scale
float scalex = values[Matrix.MSCALE_X];
float skewy = values[Matrix.MSKEW_Y];
float rScale = (float) Math.sqrt(scalex * scalex + skewy * skewy);

// calculate the degree of rotation
float rAngle = Math.round(Math.atan2(v[Matrix.MSKEW_X], v[Matrix.MSCALE_X]) * (180 / Math.PI));


来源:https://stackoverflow.com/questions/21453387/android-code-to-rotate-an-image-view-on-touch-or-drag-event

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!