Search code examples
androidandroid-viewontouchlistenerontouchdrag

Moving a View with ACTION_MOVE in Scaled Layout


Hello! Thank you for reading.

Based upon this answer, I integrated View dragging like so:

float dX, dY;

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

    switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN:

            dX = view.getX() - event.getRawX();
            dY = view.getY() - event.getRawY();
            break;

        case MotionEvent.ACTION_MOVE:

            setX(event.getRawX() + dX);
            setY(event.getRawY() + dY);
            break;

        default:
            return false;
    }  return true;
}

However, the View's position relative to my finger is proportionally offset with the scale of the parent layout. In other words, when I start zooming in the layout, View dragging breaks.

I've been debugging for quite a bit and it seems that even knowing the parent layout scale (as, say, dScale), I can't use that value in a way that fixes the offset completely.

I cannot even reach a point where the distance between my finger and the View is constant.

To note that the issue is only observable when the parent's scale is not equal to 1.

.

Thank you very much for your help!


Solution

  • For further reference, this situation can be solved by applying the parent's scale to the getRawX() methods in both occurrences. I somehow hadn't tried that...

    float dX, dY;
    
    @Override
    public boolean onTouch(View view, MotionEvent event) {
    
        switch (event.getAction()) {
    
            case MotionEvent.ACTION_DOWN:
    
                dX = view.getX() - event.getRawX() / dScale;
                dY = view.getY() - event.getRawY() / dScale;
                break;
    
            case MotionEvent.ACTION_MOVE:
    
                setX(event.getRawX() / dScale + dX);
                setY(event.getRawY() / dScale + dY);
                break;
    
            default:
                return false;
        }  return true;
    }
    

    I'd also recommend putting the MOVE case first in the switch.

    I suppose the reasoning behind this solution can be vaguely explained by "view positioning methods know how to handle scaling, touch callback methods don't".

    Hope this will help some!