3

У меня проблема с рисованием и масштабированием ImageView. Помогите мне, пожалуйста.Android zoom, drag, draw on ImageView

Когда я рисую что-то, а затем перетаскиваю или увеличиваю изображение - рисунок остается на своем месте, как вы можете видеть на снимке screencapture. И мне нужно просто рисовать на картинке и иметь возможность масштабировать и перетаскивать эту картинку.

enter image description here enter image description here

У меня есть пользовательский ImageView с этим действий:

public class DrawingView extends ImageView { 
// onTouch 
private float mX, mY; 
private static final float TOUCH_TOLERANCE = 4; 

private Path mPath; 

private boolean zoomEnabled = true; 

private Paint drawPaint, canvasPaint; 
//initial color 
private int paintColor = 0xFF660000; 
//canvas 
private Canvas drawCanvas; 
//canvas bitmap 
private Bitmap canvasBitmap; 

private static final int INVALID_POINTER_ID = -1; 

private float mPosX; 
private float mPosY; 

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

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

public DrawingView(Context context, AttributeSet attrs) { 
    this(context, attrs, 0); 
    mScaleDetector = new ScaleGestureDetector(getContext(), new ScaleListener()); 
    setupDrawing(); 
} 

public DrawingView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
    setupDrawing(); 
} 

@Override 
protected void onSizeChanged(int w, int h, int oldw, int oldh) { 

    super.onSizeChanged(w, h, oldw, oldh); 
    canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); 
    drawCanvas = new Canvas(canvasBitmap); 

} 

@Override 
public boolean onTouchEvent(MotionEvent ev) { 
    final int action = ev.getAction(); 
    mScaleDetector.onTouchEvent(ev); 
    if (zoomEnabled) { 
     switch (action & MotionEvent.ACTION_MASK) { 
      case MotionEvent.ACTION_DOWN: { 
       if (!mScaleDetector.isInProgress()) { 
        final float x = ev.getX(); 
        final float y = ev.getY(); 

        mLastTouchX = x; 
        mLastTouchY = y; 
        mActivePointerId = ev.getPointerId(0); 
       } 
       break; 
      } 
      case MotionEvent.ACTION_POINTER_1_DOWN: { 
       if (mScaleDetector.isInProgress()) { 
        final float gx = mScaleDetector.getFocusX(); 
        final float gy = mScaleDetector.getFocusY(); 
        mLastGestureX = gx; 
        mLastGestureY = gy; 
       } 
       break; 
      } 
      case MotionEvent.ACTION_MOVE: { 

       // Only move if the ScaleGestureDetector isn't processing a gesture. 
       if (!mScaleDetector.isInProgress()) { 
        final int pointerIndex = ev.findPointerIndex(mActivePointerId); 
        final float x = ev.getX(pointerIndex); 
        final float y = ev.getY(pointerIndex); 

        final float dx = x - mLastTouchX; 
        final float dy = y - mLastTouchY; 

        mPosX += dx; 
        mPosY += dy; 

        invalidate(); 

        mLastTouchX = x; 
        mLastTouchY = y; 
       } else { 
        final float gx = mScaleDetector.getFocusX(); 
        final float gy = mScaleDetector.getFocusY(); 

        final float gdx = gx - mLastGestureX; 
        final float gdy = gy - mLastGestureY; 

        mPosX += gdx; 
        mPosY += gdy; 

        invalidate(); 

        mLastGestureX = gx; 
        mLastGestureY = gy; 
       } 

       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 = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
         >> MotionEvent.ACTION_POINTER_INDEX_SHIFT; 
       final int pointerId = ev.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 = ev.getX(newPointerIndex); 
        mLastTouchY = ev.getY(newPointerIndex); 
        mActivePointerId = ev.getPointerId(newPointerIndex); 
       } else { 
        final int tempPointerIndex = ev.findPointerIndex(mActivePointerId); 
        mLastTouchX = ev.getX(tempPointerIndex); 
        mLastTouchY = ev.getY(tempPointerIndex); 
       } 
       break; 
      } 
     } 

     return true; 
    } else { 
     switch (action) { 
      case MotionEvent.ACTION_DOWN: 
       touchStart(ev.getX(), ev.getY()); 
       invalidate(); 
       break; 
      case MotionEvent.ACTION_MOVE: 
       touchMove(ev.getX(), ev.getY()); 
       invalidate(); 
       break; 
      case MotionEvent.ACTION_UP: 
       touchUp(); 
       invalidate(); 
       break; 
     } 
     return true; 
    } 
} 

@Override 
public void onDraw(Canvas canvas) { 
    canvas.save(); 
    canvas.translate(mPosX, mPosY); 

    if (mScaleDetector.isInProgress()) { 
     canvas.scale(mScaleFactor, mScaleFactor, mScaleDetector.getFocusX(), mScaleDetector.getFocusY()); 
    } 
    else{ 
     canvas.scale(mScaleFactor, mScaleFactor, mLastGestureX, mLastGestureY); 
    } 
    super.onDraw(canvas); 
    canvas.restore(); 

    canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint); 
    canvas.drawPath(mPath, drawPaint); 
} 

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, 10.0f)); 

     invalidate(); 
     return true; 
    } 
} 

private void setupDrawing(){ 
    mPath = new Path(); 
    drawPaint = new Paint(); 
    drawPaint.setColor(paintColor); 
    drawPaint.setAntiAlias(true); 
    drawPaint.setStrokeWidth(20); 
    drawPaint.setStyle(Paint.Style.STROKE); 
    drawPaint.setStrokeJoin(Paint.Join.ROUND); 
    drawPaint.setStrokeCap(Paint.Cap.ROUND); 
    canvasPaint = new Paint(Paint.DITHER_FLAG); 
} 

public void setZoomEnabled(boolean b){ 
    this.zoomEnabled = b; 
} 

private void touchStart(float x, float y) { 
    // mPath.reset(); 
    mPath.moveTo(x, y); 
    mX = x; 
    mY = y; 
} 

private void touchMove(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; 
    } 
} 

private void touchUp() { 
    mPath.lineTo(mX, mY); 
    // commit the path to our offscreen 
    drawCanvas.drawPath(mPath, drawPaint); 
    // kill this so we don't double draw 
    mPath.reset(); 
} 

И активность:

public class DrawActivity extends Activity{ 

DrawingView image; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.draw); 

    final Paint paint = new Paint(); 
    paint.setColor(MyApp.getColorRes(R.color.primary)); 
    paint.setStrokeWidth(10); 

    image = (DrawingView) findViewById(R.id.image); 

    Bitmap bmp = BitmapFactory.decodeByteArray(
      getIntent().getByteArrayExtra("byteArray"), 0, getIntent().getByteArrayExtra("byteArray").length); 


    Bitmap alteredBmp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig()); 
    final Canvas canvas = new Canvas(alteredBmp); 
    canvas.drawBitmap(bmp, 0, 0, paint); 
    image.setImageBitmap(alteredBmp); 

    ImageButton paintBtn = (ImageButton) findViewById(R.id.paint_btn); 
    paintBtn.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View button) { 
      button.setSelected(!button.isSelected()); 
      image.setZoomEnabled(!button.isSelected()); 
     } 
    }); 

} 

ответ

3

В вашем onDraw(), вы рисуете свой путь непосредственно с помощью функции представления холст. Вместо этого наведите путь на canvasBitmap через drawCanvas. Как только это будет сделано, ваш canvasBitmap будет содержать как изображение, так и рисунок. Теперь, когда вы масштабируете или перемещаете, оба будут меняться соответствующим образом, так как теперь они находятся в одном растровом изображении.

Вместо этого:

canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint); 
canvas.drawPath(mPath, drawPaint); 

ли что-то вроде этого:

drawCanvas.drawPath(mPath, drawPaint); 
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint); 
+1

Спасибо !! Ты был прав! Также мне пришлось поставить эти строки перед canvas.restore(); –

+1

Когда я рисую на zoomedview, нарисуйте неправильную координату, решите ?? – Arjun

+0

Вы можете сделать это двумя способами. Сначала нарисуйте свой холст на 0, затем нарисуйте, а затем уменьшите масштаб до исходного масштабного коэффициента. Или вы можете масштабировать координату, а затем рисовать с помощью этой координаты. – Henry