title: Android - canvas confusion (drawing and scrolling)
body: <p>I'm having a bit of confusion with <code>canvas</code> in android and was wondering if someone could clarify a few things for me.</p>
  
  <p>I currently have this code inside my View class:</p>
  
  <pre><code> class HomerView extends View { // the custom View for drawing on
      // set up Bitmap, canvas, path and paint
      private Bitmap myBitmap; // the initial image we turn into our canvas
      private Canvas myCanvas; // the canvas we are drawing on
      private Rect myRect; // the mathematical path of the lines we draw
      private Paint myBitmapPaint; // the paint we use to draw the bitmap
  
      // get the width of the entire tablet screen
      private int screenWidth = getContext().getResources()
              .getDisplayMetrics().widthPixels;
      // get the height of the entire tablet screen
      private int screenHeight = getContext().getResources()
              .getDisplayMetrics().heightPixels;
  
      private int mX, mY, iX, iY; // current x,y and initial x,y
      private static final float TOUCH_TOLERANCE = 4;
      private static final int INVALID_POINTER_ID = -1;
      private float mPosX;
      private float mPosY;
      private BitmapDrawable mImage;
      private float mLastTouchX;
      private float mLastTouchY;
      private int mActivePointerId = INVALID_POINTER_ID;
      private ScaleGestureDetector mScaleDetector;
      private float mScaleFactor = 1.f;
  
      public HomerView(Context context) { // constructor of HomerView
          super(context);
          myBitmap = Bitmap.createBitmap(screenWidth, screenHeight,
                  Bitmap.Config.ARGB_8888); // set our drawable space - the bitmap which becomes the canvas we draw on
          myCanvas = new Canvas(myBitmap); // set our canvas to our bitmap which we just set up
          myRect = new Rect(); // make a new rect
          myBitmapPaint = new Paint(Paint.DITHER_FLAG); // set dither to ON in our saved drawing - gives better color interaction
          setHorizontalScrollBarEnabled(true);
          setVerticalScrollBarEnabled(true);
          TypedArray a = context.obtainStyledAttributes(R.styleable.View);
          initializeScrollbars(a);
          a.recycle();
          computeVerticalScrollRange();
          computeHorizontalScrollRange();
          mImage = new BitmapDrawable(getResources(), myBitmap);
          mScaleDetector = new ScaleGestureDetector(context,
                  new ScaleListener());
      }
  
      public HomerView(Context context, AttributeSet attrs, int defStyle) {
          super(context, attrs, defStyle);
          mScaleDetector = new ScaleGestureDetector(context,
                  new ScaleListener());
      }
  
      public HomerView(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
      }
  
      protected void onDraw(Canvas canvas) { // method used when we want to draw something to our canvas
          super.onDraw(canvas);
          if (addObjectMode == true) {
              canvas.drawColor(Color.TRANSPARENT); // sets canvas colour
              canvas.drawBitmap(myBitmap, 0, 0, myBitmapPaint); // save the canvas to bitmap - the numbers are the x, y coords we are drawing from
              canvas.drawRect(myRect, myPaint); // draw the rectangle that the user has drawn using the paint we set up
          } else if (moveMode == true) {
              canvas.save();
              System.out.println("X: " + mPosX + " Y: " + mPosY);
              canvas.translate(mPosX, mPosY);
              canvas.scale(mScaleFactor, mScaleFactor);
              mImage.draw(canvas);
              canvas.restore();
          }
  </code></pre>
  
  <p>This is kind of an amalgamation of 2 different approaches to drawing to the screen as I understand it. My understanding is that I have <code>myBitmap</code> (which is what users drawings are drawn on) and this works fine for <em>"addObjectMode"</em>. However, <em>"moveMode"</em> is when I want the users to be able to pinch zoom scroll etc. around the house plan that they have drawn. </p>
  
  <p>Currently, I am able to draw objects fine but when I press the button to enable <code>moveMode</code>, the drawing disappears when I touch or gesture. I'm aware this is probably because of the code in <code>onDraw()</code>; but canvas's are still a bit of a mystery to me. </p>
  
  <p>Eventually, I'm going to want a basic undo/redo feature as well as saving the <code>canvas/bitmap</code> to be opened later. Can anyone offer any advice or link to any comprehensive canvas tutorials?</p>
  
  <p>EDIT: it might be useful to include my <code>onTouchEvent</code> methods too-</p>
  
  <pre><code> public boolean onTouchEvent(MotionEvent event) { // on any touch event
          if (addObjectMode == true) {
  
              float x = event.getX(); // get current X
              float y = event.getY(); // get current Y
  
              switch (event.getAction()) { // what action is the user performing?
              case MotionEvent.ACTION_DOWN: // if user is touching down
                  touch_Start(x, y);
                  invalidate();
                  break;
              case MotionEvent.ACTION_MOVE: // if user is moving finger while touched down
                  touch_Move(x, y);
                  invalidate();
                  break;
              case MotionEvent.ACTION_UP: // if user has released finger
                  touch_Up();
                  invalidate();
                  break;
              }
              return true;
          } else if (moveMode == true) {
              mScaleDetector.onTouchEvent(event);
              final int action = event.getAction();
              switch (action &amp; MotionEvent.ACTION_MASK) {
              case MotionEvent.ACTION_DOWN: {
                  final float x = event.getX();
                  final float y = event.getY();
                  mLastTouchX = x;
                  mLastTouchY = y;
                  mActivePointerId = event.getPointerId(0);
                  break;
              }
  
              case MotionEvent.ACTION_MOVE: {
                  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() &amp; MotionEvent.ACTION_POINTER_INDEX_MASK) &gt;&gt; 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;
              }
              }
              return true;
          } else {
              return false;
          }
      }
  </code></pre>