放大时,Android画布会滚动边框

时间:2015-02-03 19:59:47

标签: android android-canvas

我有一个画布,我能够缩小并滚动边界,其代码在这里

package com.mypackage.ui.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.provider.SyncStateContract;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Locale;

/**
 *
 */
public class MyDrawingView extends View {

    private static final int INVALID_POINTER_ID = -1;

    private int state = 0; //0 se dibuja - 1 se mueve

    //drawing path
    private Path drawPath;
    //drawing and canvas paint
    private Paint drawPaint, canvasPaint;

    //canvas
    private Canvas drawCanvas;
    //canvas bitmap
    private Bitmap bitmap;

    protected String tool;
    protected String color;
    protected float brushSize;

    //erase flag
    private boolean erase=false;

    public String getTool() {
        return tool;
    }

    public void setTool(String tool) {
        this.tool = tool;
    }

    public String getColor() {
        return color;
    }

    public float getBrushSize() {
        return brushSize;
    }

    public boolean isErase() {
        return erase;
    }

    private String drawId;

//    public OnSaveActionListener listener;

    private float mPosX;
    private float mPosY;

    public float getMPosX() { return mPosX; }

    public float getMPosY() { return mPosY; }

    private float mLastTouchX;
    private float mLastTouchY;
    private int mActivePointerId = INVALID_POINTER_ID;

    private ScaleGestureDetector mScaleDetector;
    private float mScaleFactor = 1.f;

    private float viewHeight;
    private float viewWidth;
    float canvasWidth, canvasHeight;

    private float minScaleFactor;

    private boolean panEnabled = true;
    private boolean zoomEnabled = true;

    public MyDrawingView(Context context) {
        super(context);
        setup();
    }

    public MyDrawingView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setup();
    }

    public MyDrawingView(Context context, AttributeSet attrs){
        super(context, attrs);
        setup();
    }

    //setup drawing
    private void setup(){
        mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener());
        //prepare for drawing and setup paint stroke properties
        drawPath = new Path();
        drawPaint = new Paint();
        drawPaint.setStyle(Paint.Style.STROKE);
        drawPaint.setStrokeJoin(Paint.Join.ROUND);
        drawPaint.setStrokeCap(Paint.Cap.ROUND);
        canvasPaint = new Paint(Paint.DITHER_FLAG);
    }

    public void setState(int state) {

        this.state = state;

    }

    public void setImageBitmap(Bitmap bmp) {
        bitmap = bmp;
        resetZoom();
        resetPan();
        invalidate();
    }

    public void setImageDrawable(Drawable drawable) {
        setImageBitmap(((BitmapDrawable) drawable).getBitmap());
    }

    public void setBitmap(Bitmap bmp) {
        setImageBitmap(bmp);
    }

    public void resetZoom() {
        mScaleFactor = 1.0f;
    }

    public void resetPan() {
        mPosX = 0f;
        mPosY = 0f;
    }

    public BitmapDrawable getImageDrawable() {
        BitmapDrawable bd = new BitmapDrawable(getContext().getResources(), bitmap);
        return bd;
    }

    public BitmapDrawable getDrawable() {
        return getImageDrawable();
    }

    //size assigned to view
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        drawCanvas = new Canvas(bitmap);
    }

    //draw the view - will be called after touch event
    @Override
    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        mScaleFactor = Math.max(mScaleFactor, minScaleFactor);

        canvasHeight = canvas.getHeight();
        canvasWidth = canvas.getWidth();

        //Save the canvas without translating (panning) or scaling (zooming)
        //After each change, restore to this state, instead of compounding
        //changes upon changes
        canvas.save();
        int maxX, minX, maxY, minY;
        //Regardless of the screen density (HDPI, MDPI) or the scale factor,
        //The image always consists of bitmap width divided by 2 pixels. If an image
        //is 200 pixels wide and you scroll right 100 pixels, you just scrolled the image

        //off the screen to the left.
        minX = (int) (((viewWidth / mScaleFactor) - bitmap.getWidth()) / 2);
        maxX = 0;
        //How far can we move the image vertically without having a gap between image and frame?
        minY = (int) (((viewHeight / mScaleFactor) - bitmap.getHeight()) / 2);
        maxY = 0;
        //Do not go beyond the boundaries of the image
        if (mPosX > maxX) {
            mPosX = maxX;
        }
        if (mPosX < minX) {
            mPosX = minX;
        }
        if (mPosY > maxY) {
            mPosY = maxY;
        }
        if (mPosY < minY) {
            mPosY = minY;
        }

        if (state == 0) {
        } else if (state == 1) {
            canvas.scale(this.mScaleFactor, this.mScaleFactor, this.mScaleDetector.getFocusX(), this.mScaleDetector.getFocusY());
        }

        canvas.translate(mPosX, mPosY);
        canvas.drawBitmap(bitmap, 0, 0, canvasPaint);
        canvas.drawPath(drawPath, drawPaint);
        canvas.restore();
        invalidate();
    }

    //register user touches as drawing action
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        mScaleDetector.onTouchEvent(event);

        float touchX = event.getX();
        float touchY = event.getY();

        if(isErase()){
            drawCanvas.drawPath(drawPath, drawPaint);
            invalidate();
        }

        //respond to down, move and up events
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:

                mLastTouchX = touchX;
                mLastTouchY = touchY;
                mActivePointerId = event.getPointerId(0);

                break;
            case MotionEvent.ACTION_MOVE:

                if (state == 0) {
                } else if (state == 1) {

                    final int pointerIndex = event.findPointerIndex(mActivePointerId);
                    final float x = event.getX(pointerIndex);
                    final float y = event.getY(pointerIndex);

                    // Only move if the ScaleGestureDetector isn't processing a gesture.
                    if (!mScaleDetector.isInProgress()) {
                        final float dx = x - mLastTouchX;
                        final float dy = y - mLastTouchY;

                        mPosX += dx;
                        mPosY += dy;

                        invalidate();
                    }

                    mLastTouchX = x;
                    mLastTouchY = y;

                }
                break;
            case MotionEvent.ACTION_UP:
                mActivePointerId = INVALID_POINTER_ID;

                break;

            case MotionEvent.ACTION_CANCEL:
                mActivePointerId = INVALID_POINTER_ID;
                break;

            case MotionEvent.ACTION_POINTER_UP:
                final int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
                        >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                final int pointerId = event.getPointerId(pointerIndex);
                if (pointerId == mActivePointerId) {
                    // This was our active pointer going up. Choose a new
                    // active pointer and adjust accordingly.
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    mLastTouchX = event.getX(newPointerIndex);
                    mLastTouchY = event.getY(newPointerIndex);
                    mActivePointerId = event.getPointerId(newPointerIndex);
                }
                break;

            default:
                return false;
        }

        return true;

    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            mScaleFactor *= detector.getScaleFactor();

            // Don't let the object get too small or too large.
            mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));

            invalidate();
            return true;
        }
    }



}

上面的代码是一个适用于the answer here

的改编版

我遇到的问题是当我放大时我无法滚动到图像的任何位置,就像角落不可更新。我知道我在界限上犯了一个错误,但我无法实现如何解决它

谢谢

0 个答案:

没有答案