当旋转android时,路径在画布的相反方向绘制

时间:2014-12-31 14:31:54

标签: android android-canvas eraser

enter image description here 嗨我正在擦除画布上绘制的位图,触摸(手指)工作正常我面临的问题是在画布路径旋转位图之后绘制相反方向意味着位图擦除在我手指触摸的相反方向。

DrawingPane.class

public class DrawingPanel extends ImageView implements OnTouchListener {


private Matrix mMatrix = new Matrix();
private float mScaleFactor = 1f;
private float mRotationDegrees = 0.f;
private float mFocusX = 0.f;
private float mFocusY = 0.f;  
private int mAlpha = 255;
private int mImageHeight, mImageWidth;

private ScaleGestureDetector mScaleDetector;
private RotateGestureDetector mRotateDetector;
private MoveGestureDetector mMoveDetector;
private ShoveGestureDetector mShoveDetector; 
private boolean isMoving=false;
EditPhotoActivity editActivity;


Bitmap overlayDefault;
Bitmap overlay;
Bitmap bmp,bmp2;
Paint pTouch; 
int whichTabSelected=0;

private Path mPath;
Display display ;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Float> xlist = new ArrayList<Float>();
private ArrayList<Float> ylist = new ArrayList<Float>();
@SuppressLint("NewApi")
public DrawingPanel(Context context, int colorPaint,Bitmap bmp) {
    super(context);


    if (Build.VERSION.SDK_INT >= 11) {
        setLayerType(View.LAYER_TYPE_HARDWARE, null);
    }
    display = ((Activity)context).getWindowManager().getDefaultDisplay();

    mFocusX = display.getWidth()/2f;
    mFocusY = display.getHeight()/2f;
    try {

        overlayDefault=bmp;
        overlay=bmp;
        overlay=overlay.copy(Config.ARGB_8888, true);
        overlay.setHasAlpha(true);

    } catch (Exception e) {

        e.printStackTrace();
    }

    mImageHeight    = getHeight();
    mImageWidth     = getWidth();


    // Setup Gesture Detectors
    mScaleDetector  = new ScaleGestureDetector(context, new ScaleListener());
    mRotateDetector = new RotateGestureDetector(context, new RotateListener());
    mMoveDetector   = new MoveGestureDetector(context, new MoveListener());
    mShoveDetector  = new ShoveGestureDetector(context, new ShoveListener());


    pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);         
    pTouch.setXfermode(new PorterDuffXfermode(Mode.CLEAR)); 
    pTouch.setColor(Color.TRANSPARENT);
    //pTouch.setMaskFilter(new BlurMaskFilter(30, Blur.SOLID));
    pTouch.setStyle(Paint.Style.STROKE);
    pTouch.setStrokeJoin(Paint.Join.ROUND);
    pTouch.setStrokeCap(Paint.Cap.ROUND);
    pTouch.setStrokeWidth(50);
    pTouch.setAntiAlias(true);
    setFocusable(true);
    setFocusableInTouchMode(true);
    mPath = new Path();
    paths.add(mPath);
}


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    mImageHeight=getHeight();
    mImageWidth=getWidth();
    bmp  = Bitmap.createScaledBitmap(overlay, w, h, false);
    bmp2  = Bitmap.createScaledBitmap(overlayDefault, w, h, false);
    overlay = bmp.copy(Config.ARGB_8888, true);
    overlayDefault = bmp2.copy(Config.ARGB_8888, true);

}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // TODO Auto-generated method stub
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
}

@Override
protected void onDraw(Canvas canvas) {

     //  mCanvas.drawBitmap(overlayDefault,0, 0, null); //exclude this line to show all as you draw

    //  mCanvas.drawCircle(X, Y, 80, pTouch);
    //draw the overlay over the background 

        float scaledImageCenterX = (mImageWidth*mScaleFactor)/2;
        float scaledImageCenterY = (mImageHeight*mScaleFactor)/2;
        mMatrix.reset();
        mMatrix.postScale(mScaleFactor, mScaleFactor);
        mMatrix.postRotate(mRotationDegrees,  scaledImageCenterX, scaledImageCenterY);

        if(isMoving)
        {
            mMatrix.postTranslate(mFocusX - scaledImageCenterX, mFocusY - scaledImageCenterY);
        }
        else
        {
              mMatrix.postTranslate(0,0);
        }

        canvas.setMatrix(mMatrix);

        canvas.drawBitmap(overlay,0,0, null);

        for (Path p : paths) {
            canvas.drawPath(p, pTouch);
         }
        super.onDraw(canvas);
}


public Bitmap getBitmap(){
    Bitmap b  = Bitmap.createScaledBitmap(overlay,display.getWidth()    ,display.getWidth(), false);
    overlay = b.copy(Config.ARGB_8888, true);
    return overlay;
}
public void setBitmap(Bitmap bmp1){
    overlay = bmp1;

    invalidate();
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 0;

public void touch_start(float x, float y) {

    if(xlist.size()>0 && ylist.size()>0){
        xlist.clear();
        ylist.clear();
    }
    xlist.add(x);
    ylist.add(y);
    mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
    mPath.transform(mMatrix, mPath);
    invalidate();
}

public void touch_move(float x, float y) {
    float dx = Math.abs(x - mX);
    float dy = Math.abs(y - mY);
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {

        mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
        mX = x;
        mY = y;
        mPath.transform(mMatrix, mPath);
    }
    xlist.add(x);
    ylist.add(y);
    invalidate();
}

public void touch_up() {
    mPath.lineTo(mX, mY);

    mPath = new Path();
    mPath.transform(mMatrix, mPath);
    paths.add(mPath);
    invalidate();
}


public void OnTouchParent(MotionEvent event){
     mScaleDetector.onTouchEvent(event);
        mRotateDetector.onTouchEvent(event);
        mMoveDetector.onTouchEvent(event);
        mShoveDetector.onTouchEvent(event);
        float scaledImageCenterX = (mImageWidth*mScaleFactor)/2;
        float scaledImageCenterY = (mImageHeight*mScaleFactor)/2;

        mMatrix.reset();
        mMatrix.postScale(mScaleFactor, mScaleFactor);
        mMatrix.postRotate(mRotationDegrees,  scaledImageCenterX, scaledImageCenterY);
        mMatrix.postTranslate(mFocusX - scaledImageCenterX, mFocusY - scaledImageCenterY);

        float x = event.getX();
        float y = event.getY();

        /*switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN:
            if(whichTabSelected==Constant.ERASE)
            {
            touch_start(x, y);
            invalidate();
            }
            break;

        case MotionEvent.ACTION_MOVE:
            if(whichTabSelected==Constant.ERASE)
            {
            touch_move(x, y);
            invalidate();
            }
            break;

        case MotionEvent.ACTION_UP:
            if(whichTabSelected==Constant.ERASE)
            {
            touch_up();
            invalidate();
            }
            break;
        }
        if(whichTabSelected==Constant.ERASE)
        {
        return true;
        }
        else
        {
            return false;
        }*/

        invalidate();

}
@Override
public boolean onTouch(View arg0, MotionEvent event) {


    if(getTabMode()==Constant.PANZOOM)
    {
    mScaleDetector.onTouchEvent(event);
    mRotateDetector.onTouchEvent(event);
    mMoveDetector.onTouchEvent(event);
    mShoveDetector.onTouchEvent(event);

    float scaledImageCenterX = (mImageWidth*mScaleFactor)/2;
    float scaledImageCenterY = (mImageHeight*mScaleFactor)/2;



    }

    float x = event.getX();
    float y = event.getY();

    switch (event.getAction()) {

    case MotionEvent.ACTION_DOWN:
        if(getTabMode()==Constant.ERASE)
        {
        touch_start(x, y);
        invalidate();
        }
        break;

    case MotionEvent.ACTION_MOVE:
        if(getTabMode()==Constant.ERASE)
        {
        touch_move(x, y);
        invalidate();
        }
        break;

    case MotionEvent.ACTION_UP:
        if(getTabMode()==Constant.ERASE)
        {
        touch_up();
        invalidate();
        }
        break;
    }


    invalidate();
    return true;
}
public void setBottomTabMode(int mode)
{
    whichTabSelected=mode;
}
public int getTabMode()
{
    return whichTabSelected;
}


private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        mScaleFactor *= detector.getScaleFactor(); // scale change since previous event

        // Don't let the object get too small or too large.

        mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 10.0f)); 
        return true;
    }
}

private class RotateListener extends RotateGestureDetector.SimpleOnRotateGestureListener {
    @Override
    public boolean onRotate(RotateGestureDetector detector) {
        mRotationDegrees -= detector.getRotationDegreesDelta();
        return true;
    }
}   

private class MoveListener extends MoveGestureDetector.SimpleOnMoveGestureListener {
    @Override
    public boolean onMove(MoveGestureDetector detector) {
        PointF d = detector.getFocusDelta();
        mFocusX += d.x;
        mFocusY += d.y;     
        isMoving=true;
        // mFocusX = detector.getFocusX();
        // mFocusY = detector.getFocusY();
        return true;
    }
}       

private class ShoveListener extends ShoveGestureDetector.SimpleOnShoveGestureListener {
    @Override
    public boolean onShove(ShoveGestureDetector detector) {
        mAlpha += detector.getShovePixelsDelta();
        if (mAlpha > 255)
            mAlpha = 255;
        else if (mAlpha < 0)
            mAlpha = 0;

        return true;
    }
}
}

2 个答案:

答案 0 :(得分:1)

我解决了我的问题。实际上,当我旋转画布时,event.getX()event.getY()没有映射到矩阵的当前旋转,所以通过在mMatrix.invert(tempMatrix); OnDraw()中添加此行并映射当前x,y in OnTouch()通过OnTouch()方法添加它。

   float[] coords = new float[] { event.getX(), event.getY() };            
   tempMatrix.mapPoints(coords);

        float x =  coords[0];//event.getX();
        float y = coords[1];//event.getY();

工作正常。

答案 1 :(得分:0)

这种效果正在发生,因为您将矩阵两次应用于路径。

执行touch_start后,touch_move / mPath.transform(mMatrix, mPath);

然后再次onDraw(Canvas canvas) canvas.setMatrix(mMatrix);然后canvas.drawPath(p, pTouch);

要解决此问题,请尝试从mPath.transform(mMatrix, mPath); / touch_start移除touch_move

另外,我不知道将矩阵直接设置到画布是否是一个好习惯。而不是canvas.setMatrix(mMatrix);,我宁愿做以下事情:

    canvas.save();
    canvas.concat(mMatrix);
    //write the code....
    canvas.restore();