【问题标题】:Android code to rotate an image view on touch or drag event用于在触摸或拖动事件时旋转图像视图的 Android 代码
【发布时间】:2014-03-13 17:53:41
【问题描述】:

我需要在触摸和拖动时旋转图像。现在当用户按下imageView 并移动以进行旋转时,我需要一个度角,请帮助我。

imageView.setRotation(degree);

我需要MotionEvent.ACTION_MOVE block.中这个度数变量的值

【问题讨论】:

    标签: android android-imageview


    【解决方案1】:

    你想在你的项目类中使用 RotateGestureDetector,如下所示..

    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);
    }
    }
    

    它易于使用的类和有效的旋转.. 我希望有用....

    【讨论】:

    • 在增量变大后发送完全随机的增量。非常敏感的方式。
    【解决方案2】:

    为了移动和缩放图像,我们将在 ImageView 类中使用一个简洁的小功能,称为矩阵变换。使用矩阵,我们可以表示我们想要对图像进行的任何类型的平移、旋转或倾斜

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

    在手势中

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

    你需要玩 Matrix 类。在这里您可以获得翻译并使用它可以获得旋转角度。 here 是它的教程。

    在执行转换(例如围绕任意点旋转位图)后,比例会丢失。当然,这是有道理的,因为位图在相同的范围内旋转。

    现在要获得真正的比例,以及最可靠的旋转度数,我必须遵循这种方法。希望它能为你们其他人节省一两个晚上。

    你可以得到如下角度:-

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

    【讨论】:

    • 在哪里使用 rScale@praveen Sharma
    猜你喜欢
    • 1970-01-01
    • 2012-07-09
    • 1970-01-01
    • 1970-01-01
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多