简体   繁体   中英

Rotate, Zoom/Scale, Drag Bitmap with onTouchEvent Android

i want to be able to rotate & zoom/scale my bitmap with fingers, i already look for all of the example project for this, but all of them aren't match with my code. This is my code for my onTouchListener.

public class MyView extends View {
    private float mX, mY;
    private float XText, YText;
    private float Textpixel;
    private static final float TOUCH_TOLERANCE = 2;

    //image
    float xImage = 200;
    float yImage = 200;

    public MyView(Context c) {
        super(c);
        mCanvas     = new Canvas();
        mPath       = new Path();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh );
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if ( layouttype == "small"){
            Textpixel   = 16f;
        }else if(layouttype == "normal"){
            Textpixel   = 16f;
        }else if (layouttype == "large"){
            Textpixel   = 18f;
        }else {
            Textpixel   = 20f;
        }

        if(bmImgAttach != null) {
            canvas.drawBitmap(bmImgAttach, xImage, yImage, null);
        }
    }

    public void touch_start(float x, float y, MotionEvent event) {
        if (isImage) {
            if(isTouchImage) {
                xImage = event.getX();
                yImage = event.getY();
            }
        }
    }

    private void touch_move(float x, float y, MotionEvent event) {
        if(isImage) {
            if(isTouchImage) {
                xImage = event.getX();
                yImage = event.getY();
            }
        }
    }

    private void touch_up(float x, float y, MotionEvent event) {
        if(isImage) {
            if(isTouchImage) {
                xImage = event.getX();
                yImage = event.getY();
            }
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final float x = event.getX();
        final float y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                touch_start(x, y, event);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touch_move(x, y, event);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touch_up(x, y, event);
                invalidate();
                break;
        }return true;
    }
}

i created a different method for each event like:

  • touch_start method for ACTION_DOWN event
  • touch_move method for ACTION_MOVE event
  • touch_up method for ACTION_UP event

The Matrix class in Android uses a 3×3 matrix to achieve all of the 2D transformations.

Here's a quick implementation of Android's multi touch feature – one finger to move, two to zoom, and three to rotate the image.

public class MultiTouch extends Activity implements OnTouchListener {

// these matrices will be used to move and zoom image
private Matrix matrix = new Matrix();
private Matrix savedMatrix = new Matrix();
// we can be in one of these 3 states

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

// remember some things for zooming

private PointF start = new PointF(); 
private PointF mid = new PointF();
private float oldDist = 1f;
private float d = 0f;
private float newRot = 0f;
private float[] lastEvent = null;

@Override
public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView view = (ImageView) findViewById(R.id.imageView);
view.setOnTouchListener(this);

}

public boolean onTouch(View v, MotionEvent event) {

// handle touch events here
ImageView view = (ImageView) v;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = DRAG;
lastEvent = null;
break;

case MotionEvent.ACTION_POINTER_DOWN:

oldDist = spacing(event);
if (oldDist > 10f) {
savedMatrix.set(matrix);
midPoint(mid, event);
mode = ZOOM;
}

lastEvent = new float[4];
lastEvent[0] = event.getX(0);
lastEvent[1] = event.getX(1);
lastEvent[2] = event.getY(0);
lastEvent[3] = event.getY(1);
d = rotation(event);
break;

case MotionEvent.ACTION_UP:

case MotionEvent.ACTION_POINTER_UP:

mode = NONE;
lastEvent = null;
break;

case MotionEvent.ACTION_MOVE:

if (mode == DRAG) {

matrix.set(savedMatrix);
float dx = event.getX() - start.x;
float dy = event.getY() - start.y;
matrix.postTranslate(dx, dy);

} else if (mode == ZOOM) {
float newDist = spacing(event);

if (newDist > 10f) {

matrix.set(savedMatrix);
float scale = (newDist / oldDist);
matrix.postScale(scale, scale, mid.x, mid.y);

}

if (lastEvent != null && event.getPointerCount() == 3) {

newRot = rotation(event);
float r = newRot - d;
float[] values = new float[9];
matrix.getValues(values);
float tx = values[2];
float ty = values[5];
float sx = values[0];
float xc = (view.getWidth() / 2) * sx;
float yc = (view.getHeight() / 2) * sx;
matrix.postRotate(r, tx + xc, ty + yc);

}
}
break;
}
view.setImageMatrix(matrix);
return true;
}
 /**

* Determine the space between the first two fingers

*/

private float spacing(MotionEvent event) {

float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
return FloatMath.sqrt(x * x + y * y);

}

/**

* Calculate the mid point of the first two fingers

*/

private void midPoint(PointF point, MotionEvent event) {

float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
/**

* Calculate the degree to be rotated by.

* @param event

* @return Degrees

*/

private float rotation(MotionEvent event) {

double delta_x = (event.getX(0) - event.getX(1));
double delta_y = (event.getY(0) - event.getY(1));
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);

}

}

And, use the scaleType=matrix for ImageView, like this

<ImageView
    android:id="@+id/imageView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scaleType="matrix"
    android:src="@drawable/app_icon" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM