旋转和缩放以及在Android中使用多点触控移动 [英] rotation and scaling and move using multi touch in android

查看:56
本文介绍了旋转和缩放以及在Android中使用多点触控移动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在多点触摸事件下旋转,缩放和移动图像,这似乎可以正常工作,但效果并不理想.我真的很想修正我的错误代码,所以请帮助我.我的代码在那里

i want to rotate and scale and move the image on multi touch event, it seems to be working, but it's not working perfectly. I really want to fix my wrong code up, so please help me. my code is there

public class ImageControl extends Activity {
    DragView dragView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        dragView = new DragView(this);
        setContentView(dragView);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.image_control, menu);
        return true;
    }
    class DragView extends ImageView
    {
        private Bitmap bitmap;

                private float width;
        private float height;

        private float startX=0;
        private float startY=0;

        private float userX=0;
        private float userY=0;

        private Paint paint;

        private float oldDistance = 1f;
        private float newDistance = 1f;

        private Rect rect;

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

        private int lastAngle=0;

        private int thisAngle=0;

        private int deltaAngle;

        private int angle;

        int rotateX, rotateY;

        private Matrix mat;

        private float x1;
        private float y1;

        public DragView(Context context){
            super(context);
            init();
            setImage(context);
        }
        private void init(){
            paint = new Paint();
            paint.setColor(Color.RED);
            paint.setStyle(Paint.Style.STROKE);
            paint.setAntiAlias(true);
            mat = new Matrix();
        }
        private void setImage(Context context){
            bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.android);
            width = bitmap.getWidth();
            height = bitmap.getHeight();
        }
        public void onDraw(Canvas canvas){
            if(bitmap!=null)
            {
                canvas.drawBitmap(bitmap, mat, null);
                canvas.drawRect(userX, userY, userX+width, userY+height, paint);
            }
        }
        public Rect getRect(){
            rect = new Rect();
            rect.set((int)userX, (int)userY, (int)(userX+width), (int)(userY+height));
            return rect;
        }
        public void setXY(float x, float y){
            startX = x;
            startY= y;

        }
        public boolean onTouchEvent(MotionEvent event){
            x1 = event.getX(0);
            y1 = event.getY(0);
            int act = event.getAction();
            switch(act&MotionEvent.ACTION_MASK){
            case MotionEvent.ACTION_DOWN:
                setXY(x1, y1);
                mode=DRAG;
                break;
            case MotionEvent.ACTION_MOVE:
                if(mode==ZOOM){
                    newDistance = spacing(event);
                    float scale2 = FloatMath.sqrt(((newDistance-oldDistance)*(newDistance-oldDistance))
                            /(height*height+width*width));
                    float scale = newDistance / oldDistance;
                    if(newDistance - oldDistance > 0){
                        setZoom(scale, scale2);
                    }else if(oldDistance - newDistance > 0){
                        setZoom(scale, -scale2);
                    }
                    setRotate(event, x1, y1);
                }
                else if(mode==DRAG){
                    setLastXY(x1-startX, y1-startY);
                    setXY(x1, y1);
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_POINTER_UP:
                mode = NONE;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                    mode = ZOOM;
                    float value = spacing(event);
                    oldDistance = value;
                    newDistance = value;
                    break;
            case MotionEvent.ACTION_CANCEL:
            default:
                    break;
            }
            return true;
        }
        private void setLastXY(float x, float y){
            userX += x;
            userY += y;
            mat.setTranslate(userX, userY);
            invalidate();
        }
        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);
        }
        private void setZoom(float scale, float scale2){

            userY=userY-(height*scale2/2);
            userX=userX-(width*scale2/2); 
            height=height*(1+scale2);
            width=width*(1+scale2);
            Log.d("ZoomTAG", "scale:"+scale);
            mat.postScale(scale, scale, userX+width/2, userY+height/2);
            oldDistance = newDistance;
            invalidate();
        }
        private void setRotate(MotionEvent event, float x1, float y1){
            float x2 = event.getX(1);
            float y2 = event.getY(1);
            thisAngle = (int)Math.toDegrees(Math.atan2(-(y2-y1), x2-x1));
            if(lastAngle==0){
                lastAngle=thisAngle;
            }
            deltaAngle = thisAngle-lastAngle;
            angle += -deltaAngle;
            lastAngle = thisAngle;
            float minX = Math.min(x1, x2);
            float minY = Math.min(y1, y2);
            rotateX = (int)minX + (Math.abs((int)(x1-x2))/2);
            rotateY = (int)minY + (Math.abs((int)(y1-y2))/2);
            Log.d("TAG", "Angle : " + angle);
            mat.postRotate(angle, userX+width/2, userY+height/2);
            invalidate();
        }
    }
}

推荐答案

最好的方法是使用矩阵进行更改(调整大小,旋转),而不会造成任何质量损失. 尝试类似的操作并仔细看一下ACTION_DOWN和ACTION_MOVE:

The best way is to use a matrix for making changes (resize, rotate) without any quality loss. Try something like this and look carefully at ACTION_DOWN and ACTION_MOVE:

import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;

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

}

这篇关于旋转和缩放以及在Android中使用多点触控移动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆