2

我正在绘制位图并尝试使用 Canvas 对其进行一些绘制。对于绘图,每当用户在其表面上绘制某些东西时,我都会添加路径。我已经在位图上实现了捏缩放和拖动功能,但是当用户缩放位图并在其上绘制一些东西时,路径无法正确绘制。我正在使用 Matrix 进行缩放和拖动功能。我的问题是使用带有矩阵的路径。

4

1 回答 1

1

This is a working example where you can see how to implement a draggable and zoomable Path:

MainActivity

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;

public class DrawActivity extends Activity {

        DrawView drawView;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            // Set full screen view
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                                 WindowManager.LayoutParams.FLAG_FULLSCREEN);
            requestWindowFeature(Window.FEATURE_NO_TITLE);

            drawView = new DrawView(DrawActivity.this);

            setContentView(drawView);
        }    
}

DrawView

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.view.WindowManager;

public class DrawView extends View {

    Context ctx;

    static final String TAG = "DrawView";

    Paint paint = new Paint();

    //These two constants specify the minimum and maximum zoom
    private static float MIN_ZOOM = 3f;
    private static float MAX_ZOOM = 10f;

    private float scaleFactor = 3.f;
    private ScaleGestureDetector detector;

    //These two variables keep track of the X and Y coordinate of the finger when it first
    //touches the screen
    private float startX = 0f;
    private float startY = 0f;

    //These two variables keep track of the amount we need to translate the canvas along the X
    //and the Y coordinate
    private float translateX = 0f;
    private float translateY = 0f;

    //These two variables keep track of the amount we translated the X and Y coordinates, the last time we
    //panned.
    private float previousTranslateX = 0f;
    private float previousTranslateY = 0f; 

    private boolean dragged = false;

// Used for set first translate to a quarter of screen
    private float displayWidth;
    private float displayHeight;

    public DrawView(Context context)
    {
        super(context);

        ctx = context;

        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();

        DisplayMetrics metrics = new DisplayMetrics();

        display.getMetrics(metrics);

        displayWidth = metrics.widthPixels;
        displayHeight = metrics.heightPixels;

        translateX = displayWidth/4;
        translateY = displayHeight/4; 

        previousTranslateX = displayWidth/4;
        previousTranslateY = displayHeight/4;

        detector = new ScaleGestureDetector(context, new ScaleListener());

        setFocusable(true);
        setFocusableInTouchMode(true);       

// Path's color
        paint.setColor(Color.GRAY);
        paint.setAntiAlias(false); 
    }

    @Override
    public void onDraw(Canvas canvas) {     
        super.onDraw(canvas);

        canvas.save();

        //We're going to scale the X and Y coordinates by the same amount
        canvas.scale(scaleFactor, scaleFactor, 0, 0);

        //We need to divide by the scale factor here, otherwise we end up with excessive panning based on our zoom level
        //because the translation amount also gets scaled according to how much we've zoomed into the canvas.
        canvas.translate((translateX) / scaleFactor, (translateY) / scaleFactor);

        canvas.drawRect(0, 0, 100, 100, paint);

        canvas.restore(); 

    }   

    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction() & MotionEvent.ACTION_MASK) {

        case MotionEvent.ACTION_DOWN:

// First finger is on screen

            //We assign the current X and Y coordinate of the finger to startX and startY minus the previously translated
            //amount for each coordinates This works even when we are translating the first time because the initial
            //values for these two variables is zero.
            startX = event.getX() - previousTranslateX;
            startY = event.getY() - previousTranslateY;
            break;

        case MotionEvent.ACTION_MOVE:

// first finger is moving on screen  
// update translation value to apply on Path

            translateX = event.getX() - startX;
            translateY = event.getY() - startY;             

            break;

        case MotionEvent.ACTION_UP:

// No more fingers on screen

            // All fingers went up, so let's save the value of translateX and translateY into previousTranslateX and
            //previousTranslate
            previousTranslateX = translateX;
            previousTranslateY = translateY;
            break;

// All touch events are sended to ScaleListener
        detector.onTouchEvent(event);

        return true;
    }   

    class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

        @Override
        public boolean onScale(ScaleGestureDetector detector) {


            scaleFactor *= detector.getScaleFactor();
            scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM));

            invalidate();
            return true;
        }   
    }
}
于 2013-03-06T16:10:44.637 回答