Use ScaleGestureDetector

Description

The following code shows how to Use ScaleGestureDetector.

Code revised from
Android Recipes:A Problem-Solution Approach
http://www.apress.com/9781430234135
ISBN13: 978-1-4302-3413-5

Example


/*from  w w  w  .j  ava  2 s  .c om*/
import android.content.Context;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.SimpleOnScaleGestureListener;
import android.widget.ImageView;

import android.app.Activity;
import android.os.Bundle;

public class ImageActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        RotateZoomImageView imageView = new RotateZoomImageView(this);
        imageView.setImageResource(R.drawable.ic_launcher);
        
        setContentView(imageView);
    }
}
class RotateZoomImageView extends ImageView {

    private ScaleGestureDetector mScaleDetector;
    private Matrix mImageMatrix;
    /* Last Rotation Angle */
    private int mLastAngle = 0;
    /* Pivot Point for Transforms */
    private int mPivotX, mPivotY;
    
    public RotateZoomImageView(Context context) {
        super(context);
        init(context);
    }

    public RotateZoomImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public RotateZoomImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context) {
        mScaleDetector = new ScaleGestureDetector(context, mScaleListener);
        
        setScaleType(ScaleType.MATRIX);
        mImageMatrix = new Matrix();
    }

    /*
     * Use onSizeChanged() to calculate values based on the view's size.
     * The view has no size during init(), so we must wait for this
     * callback.
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        if (w != oldw || h != oldh) {
            //Shift the image to the center of the view
            int translateX = Math.abs(w - getDrawable().getIntrinsicWidth()) / 2;
            int translateY = Math.abs(h - getDrawable().getIntrinsicHeight()) / 2;
            mImageMatrix.setTranslate(translateX, translateY);
            setImageMatrix(mImageMatrix);
            //Get the center point for future scale and rotate transforms
            mPivotX = w / 2;
            mPivotY = h / 2;
        }
    }
    
    private SimpleOnScaleGestureListener mScaleListener = new SimpleOnScaleGestureListener() {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            // ScaleGestureDetector calculates a scale factor based on whether
            // the fingers are moving apart or together
            float scaleFactor = detector.getScaleFactor();
            //Pass that factor to a scale for the image
            mImageMatrix.postScale(scaleFactor, scaleFactor, mPivotX, mPivotY);
            setImageMatrix(mImageMatrix);
            
            return true;
        }
    };
    
    /*
     * Operate on two-finger events to rotate the image.
     * This method calculates the change in angle between the
     * pointers and rotates the image accordingly.  As the user
     * rotates their fingers, the image will follow.
     */
    private boolean doRotationEvent(MotionEvent event) {
        //Calculate the angle between the two fingers
        float deltaX = event.getX(0) - event.getX(1);
        float deltaY = event.getY(0) - event.getY(1);
        double radians = Math.atan(deltaY / deltaX);
        //Convert to degrees
        int degrees = (int)(radians * 180 / Math.PI);
        
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            //Mark the initial angle
            mLastAngle = degrees;
            break;
        case MotionEvent.ACTION_MOVE:
            // ATAN returns a converted value between -90deg and +90deg
            // which creates a point when two fingers are vertical where the
            // angle flips sign.  We handle this case by rotating a small amount
            // (5 degrees) in the direction we were traveling
            
            if ((degrees - mLastAngle) > 45) {
                //Going CCW across the boundary
                mImageMatrix.postRotate(-5, mPivotX, mPivotY);
            } else if ((degrees - mLastAngle) < -45) {
                //Going CW across the boundary
                mImageMatrix.postRotate(5, mPivotX, mPivotY);
            } else {
                //Normal rotation, rotate the difference
                mImageMatrix.postRotate(degrees - mLastAngle, mPivotX, mPivotY);
            }
            //Post the rotation to the image
            setImageMatrix(mImageMatrix);
            //Save the current angle
            mLastAngle = degrees;
            break;
        }
        
        return true;
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            // We don't care about this event directly, but we declare
            // interest so we can get later multi-touch events.
            return true;
        }
        
        switch (event.getPointerCount()) {
        case 3:
            // With three fingers down, zoom the image
            // using the ScaleGestureDetector
            return mScaleDetector.onTouchEvent(event);
        case 2:
            // With two fingers down, rotate the image
            // following the fingers
            return doRotationEvent(event);
        default:
            //Ignore this event
            return super.onTouchEvent(event);
        }
    }
}
Use ScaleGestureDetector




















Home »
  Android »
    Android UI »




UI Basics
Action Bar
Animation
Button
Canvas
CheckBox
Clock Date Picker
Dialog
EditText
Event
Fragment
Gesture
GridView
ImageView
Layout
ListView
Map
Menu
Model
OpenGL
ProgressBar
RadioButton
Spinner
Tab
TextView
Thread
Toast
Video
View
WebView