Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setPivotX works strange on scaled View

I found out that setPivotX (also setPivotY) works strange in Android. If you set pivot when view's scale is set to 1.00f nothing happens (just pivot changes). But if the scale isn't equal 1.0f (e.g. setScaleX(0.9f)) and you set the pivot the view moves relatively(?) to the new pivot. Isn't it strange? I know that horizontal and vertical positions (translations) are NOT related to the pivot value, but why the view moves with scale factor other than 1.0f?

Please check this out with and without the scaling part.

public class ScaleView extends View {

private final ScaleGestureDetector mScaleGestureDetector;

public ScaleView(Context context, AttributeSet attrs) {
    super(context, attrs);


    //setScaleX(0.9f);
    //setScaleY(0.9f);

    mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureDetector.OnScaleGestureListener() {

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            // does nothing intentionally
        }

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            setPivotX(detector.getFocusX());
            setPivotY(detector.getFocusY());
            return true;
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            return false;
        }
    });
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    mScaleGestureDetector.onTouchEvent(event);
    return super.onTouchEvent(event);
}
}

How do I set the same position of the view, which was before the pivot changed?

like image 394
tomrozb Avatar asked Jan 19 '13 13:01

tomrozb


2 Answers

I solved the problem. Here is the working code:

@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
    float newX = detector.getFocusX();
    float newY = detector.getFocusY();
    setTranslationX(getTranslationX() + (getPivotX() - newX) * (1 - getScaleX()));
    setTranslationY(getTranslationY() + (getPivotY() - newY) * (1 - getScaleY()));
    setPivotX(newX);
    setPivotY(newY);
    return true;
}

The main problem is to understand how pivot works on scaled views, then there shouldn't be any problems with strange pivot behaviour.

like image 155
tomrozb Avatar answered Oct 24 '22 02:10

tomrozb


@aleien, I can answer your question. When setting a new pivot, view's properties will be recalculated. Android rescale the original view with new pivot but the same scale value which leads to new scaled view has an offset between the old scaled view. The offset is just (getPivotX() - newX) * (1 - getScaleX()), in order to counteract this offset, we can use setTranslationX(). Hope my answer can help you!

like image 3
Ryan Avatar answered Oct 24 '22 01:10

Ryan