Search code examples
androidcanvasdrag-and-dropscalemulti-touch

Android: Is this not how drawing a canvas works?


Am I misunderstanding how translating and scaling a canvas should work? I created a custom view that I can drag and zoom, but it's inside the bounds I set. I thought translating the canvas would redraw the bounds? I want to be able to drag and zoom the image on the whole screen, not in a viewport! I assumed translating the canvas would adjust the viewport.

Am I thinking about this the wrong way?

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.save();
    canvas.translate(mPosX, mPosY);
    canvas.scale(mScaleFactor, mScaleFactor);
    mIcon.draw(canvas);
    canvas.restore();
}

This is how I created the view. So basically it is stuck in this 250 x 250 box. I need the view to actually drag around.. I get the feeling I'm doing something stupid but I can't produce the behavior I'm looking for.

    MultiTouchImageView view = new MultiTouchImageView(this);
    view.setLayoutParams(new RelativeLayout.LayoutParams(250, 250));

Solution

  • You can set margins to move view in layout. I've created test project to show the idea, it looks like that:

    public class DragView extends View {
    
        private float mLastTouchX;
        private float mLastTouchY;
    
        private float mDeltaX;
        private float mDeltaY;
    
        public DragView(Context context) {
            super(context);
            init();
        }
    
        public DragView(final Context context, final AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        private void init() {
            setOnTouchListener(new OnTouchListener() {
    
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    final int action = event.getAction();
    
                    mLastTouchX = event.getRawX();
                    mLastTouchY = event.getRawY();
    
                    switch (action) {
                    case MotionEvent.ACTION_DOWN: {
                        RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) getLayoutParams();
                        mDeltaX = mLastTouchX - lParams.leftMargin;
                        mDeltaY = mLastTouchY - lParams.topMargin;
    
                        break;
                    }
                    case MotionEvent.ACTION_MOVE: {
                        mLastTouchX = event.getRawX();
                        mLastTouchY = event.getRawY();
    
                        final RelativeLayout.LayoutParams params = (LayoutParams) getLayoutParams();
                        params.leftMargin = (int) (mLastTouchX - mDeltaX);
                        params.topMargin = (int) (mLastTouchY - mDeltaY);
                        setLayoutParams(params);
    
                        break;
                    }
                    }
    
                    return true;
                }
            });
        }
    
    }