1

在此处输入图像描述 嗨,我正在擦除用触摸(手指)在画布上绘制的位图,它工作正常我面临的问题是在画布路径上旋转位图后以相反方向绘制意味着位图擦除在我的手指触摸的相反方向上。

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

2 回答 2

1

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

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

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

它工作正常。

于 2015-01-12T12:05:41.197 回答
0

之所以会出现这种效果,是因为您将矩阵两次应用于路径。

一旦在touch_start/touch_move通过做mPath.transform(mMatrix, mPath);

然后又在onDraw(Canvas canvas)by canvas.setMatrix(mMatrix);then 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();
于 2015-01-09T17:59:29.723 回答