自定义视图位置在更改枢轴点时跳跃的问题。

huangapple go评论86阅读模式
英文:

Issue with Custom View Position Jump when Changing Pivot Point

问题

I'm encountering an unexpected behavior in my Android app involving a custom view named MyView. I'm attempting to achieve both translation and rotation effects on this view. When the pivot point is set to the center of the view, everything work as expected. However, as soon as I change the pivot point (for instance, to "Point 2" selected from a spinner), the view unexpectedly jumps to a different position, as illustrated in this GIF:

自定义视图位置在更改枢轴点时跳跃的问题。

Edit:

Observations:

  • The issue primarily arises when the view is rotated. If the view has no rotation (rotation = 0), changing the pivot point doesn't cause any problems.
  • Also if before changing the pivot point, I restore the view to its initial rotation (rotation = 0) this prevent also the issue from occurring.
    To illustrate this point further, here's an example:

自定义视图位置在更改枢轴点时跳跃的问题。

Could anyone kindly advise on what might be causing the view displacement when changing the pivot point and suggest potential fixes? Your help is much appreciated.

Below is the complete code:

// MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FixedPosLayout fixedPosLayout = findViewById(R.id.fixedPosLayout);

        MyView myView = new MyView(this);

        FixedPosLayout.LayoutParams params =
                new FixedPosLayout.LayoutParams(200, 400, 300, 80);

        fixedPosLayout.addView(myView, params);

        ImageButton moveLeftButton = findViewById(R.id.moveLeftButton);
        ImageButton moveRightButton = findViewById(R.id.moveRightButton);
        ImageButton moveUpButton = findViewById(R.id.moveUpButton);
        ImageButton moveBottomButton = findViewById(R.id.moveBottomButton);

        ImageButton rotateLeftButton = findViewById(R.id.rotateLeftButton);
        ImageButton rotateRightButton = findViewById(R.id.rotateRightButton);

        AppCompatButton resetButton = findViewById(R.id.resetButton);

        Spinner spinner = findViewById(R.id.pivotPointSpinner);

        float d = 10;
        float r = 10;

        moveLeftButton.setOnClickListener(v -> myView.moveLeftBy(d));
        moveRightButton.setOnClickListener(v -> myView.moveRightBy(d));
        moveUpButton.setOnClickListener(v -> myView.moveUpBy(d));
        moveBottomButton.setOnClickListener(v -> myView.moveDownBy(d));
        rotateRightButton.setOnClickListener(v -> myView.rotateClockwiseBy(r));
        rotateLeftButton.setOnClickListener(v -> myView.rotateConterClockwiseBy(r));

        resetButton.setOnClickListener(v -> {
            myView.reset();
            spinner.setSelection(0); // Select first item
        });

        // Spinner
        String[] items = {"Center Point", "Point 1", "Point 2"};

        ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
                android.R.layout.simple_spinner_item, items);

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        spinner.setAdapter(adapter);

        // Handle spinner click
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                myView.setPivotPoint(position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                myView.setPivotPoint(0); // Set center point as default pivot point
            }
        });
    }
}

// MyView.java

public class MyView extends View {

    public static final int RADIUS = 24; // Anchor radius
    public static final int OFFSET = 1;

    private final Paint paint;

    public RectF rectPoint1;
    public RectF rectPoint2;

    public MyView(Context context) {
        super(context);

        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);

        rectPoint1 = new RectF();
        rectPoint2 = new RectF();
    }

    public void moveRightBy(float dRight) {
        setX(getX() + dRight);
    }

    public void moveLeftBy(float dLeft) {
        moveRightBy(-dLeft);
    }

    public void moveDownBy(float dDown) {
        setY(getY() + dDown);
    }

    public void moveUpBy(float dUp) {
        moveDownBy(-dUp);
    }

    public void rotateClockwiseBy(float dDegree) {
        setRotation(getRotation() + dDegree);
    }

    public void rotateConterClockwiseBy(float dDegree){
        rotateClockwiseBy(-dDegree);
    }

    public void setPivotPoint(int position) {
        switch (position) {
            // Set center point as pivot
            case 0: {
                float width = getWidth();
                float height = getHeight();

                setPivotX(width/2);
                setPivotY(height/2);
                break;
            }

            // Set Point 1 as pivot
            case 1: {
                setPivotX(rectPoint1.centerX());
                setPivotY(rectPoint1.centerY());
                break;
            }

            // Set Point 2 as pivot
            case 2: {
                setPivotX(rectPoint2.centerX());
                setPivotY(rectPoint2.centerY());
                break;
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        float width = getWidth();
        float height = getHeight();

        //Draw line between anchor points
        canvas.drawLine(
                rectPoint1.centerX(), rectPoint1.centerY(),
                rectPoint2.centerX(), rectPoint2.centerY(), paint);

        //Draw anchor circle
        canvas.drawCircle(rectPoint1.centerX(), rectPoint1.centerY(), RADIUS, paint);
        canvas.drawCircle(rectPoint2.centerX(), rectPoint2.centerY(), RADIUS, paint);

        //Draw bounding rect
        canvas.drawRect(OFFSET, OFFSET, width - OFFSET, height - OFFSET, paint);

        // Draw anchors label
        canvas.drawText("1", rectPoint1.centerX(), rectPoint1.centerY(), paint);
        canvas.drawText("2", rectPoint2.centerX(), rectPoint2.centerY(), paint);

        // Draw small circle at the center
        canvas.drawCircle(width/2f, height/2f, 4, paint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        //Recompute anchors rect
        rectPoint1.set(
                OFFSET, h /2f - RADIUS + OFFSET,
                2*RADIUS, h /2f + RADIUS - OFFSET
        );

        rectPoint2.set(
                w - 2*RADIUS, h /2f - RADIUS + OFFSET,
                w - OFFSET, h /2f + RADIUS - OFFSET
        );
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Measure exactly
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        setMeasuredDimension(width, height);
    }
英文:

I'm encountering an unexpected behavior in my Android app involving a custom view named MyView. I'm attempting to achieve both translation and rotation effects on this view. When the pivot point is set to the center of the view, everything work as expected. However, as soon as I change the pivot point (for instance, to "Point 2" selected from a spinner), the view unexpectedly jumps to a different position, as illustrated in this GIF:

自定义视图位置在更改枢轴点时跳跃的问题。

Edit:

Observations:

  • The issue primarily arises when the view is rotated. If the view has no rotation (rotation = 0), changing the pivot point doesn't cause any problems.
  • Also if before changing the pivot point, I restore the view to its initial rotation (rotation = 0) this prevent also the issue from occurring.
    To illustrate this point further, here's an example:

自定义视图位置在更改枢轴点时跳跃的问题。

Could anyone kindly advise on what might be causing the view displacement when changing the pivot point and suggest potential fixes? Your help is much appreciated.

Below is the complete code:

// MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        FixedPosLayout fixedPosLayout = findViewById(R.id.fixedPosLayout);

        MyView myView = new MyView(this);

        FixedPosLayout.LayoutParams params =
                new FixedPosLayout.LayoutParams(200, 400, 300, 80);

        fixedPosLayout.addView(myView, params);

        ImageButton moveLeftButton = findViewById(R.id.moveLeftButton);
        ImageButton moveRightButton = findViewById(R.id.moveRightButton);
        ImageButton moveUpButton = findViewById(R.id.moveUpButton);
        ImageButton moveBottomButton = findViewById(R.id.moveBottomButton);

        ImageButton rotateLeftButton = findViewById(R.id.rotateLeftButton);
        ImageButton rotateRightButton = findViewById(R.id.rotateRightButton);

        AppCompatButton resetButton = findViewById(R.id.resetButton);

        Spinner spinner = findViewById(R.id.pivotPointSpinner);

        float d = 10;
        float r = 10;

        moveLeftButton.setOnClickListener(v -&gt; myView.moveLeftBy(d));
        moveRightButton.setOnClickListener(v -&gt; myView.moveRightBy(d));
        moveUpButton.setOnClickListener(v -&gt; myView.moveUpBy(d));
        moveBottomButton.setOnClickListener(v -&gt; myView.moveDownBy(d));
        rotateRightButton.setOnClickListener(v -&gt; myView.rotateClockwiseBy(r));
        rotateLeftButton.setOnClickListener(v -&gt; myView.rotateConterClockwiseBy(r));

        resetButton.setOnClickListener(v -&gt; {
            myView.reset();
            spinner.setSelection(0); // Select first item
        });

        // Spinner
        String[] items = {&quot;Center Point&quot;, &quot;Point 1&quot;, &quot;Point 2&quot;};

        ArrayAdapter&lt;String&gt; adapter = new ArrayAdapter&lt;&gt;(this,
                android.R.layout.simple_spinner_item, items);

        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

        spinner.setAdapter(adapter);

        // Handle spinner click
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView&lt;?&gt; parent, View view, int position, long id) {
                myView.setPivotPoint(position);
            }

            @Override
            public void onNothingSelected(AdapterView&lt;?&gt; parent) {
                myView.setPivotPoint(0); // Set center point as default pivot point
            }
        });
    }
}

// MyView.java

public class MyView extends View {

    public static final int RADIUS = 24; // Anchor radius
    public static final int OFFSET = 1;

    private final Paint paint;

    public RectF rectPoint1;
    public RectF rectPoint2;

    public MyView(Context context) {
        super(context);

        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);

        rectPoint1 = new RectF();
        rectPoint2 = new RectF();
    }

    public void moveRightBy(float dRight) {
        setX(getX() + dRight);
    }

    public void moveLeftBy(float dLeft) {
        moveRightBy(-dLeft);
    }

    public void moveDownBy(float dDown) {
        setY(getY() + dDown);
    }

    public void moveUpBy(float dUp) {
        moveDownBy(-dUp);
    }

    public void rotateClockwiseBy(float dDegree) {
        setRotation(getRotation() + dDegree);
    }

    public void rotateConterClockwiseBy(float dDegree){
        rotateClockwiseBy(-dDegree);
    }

    public void setPivotPoint(int position) {
        switch (position) {
            // Set center point as pivot
            case 0: {
                float width = getWidth();
                float height = getHeight();

                setPivotX(width/2);
                setPivotY(height/2);
                break;
            }

            // Set Point 1 as pivot
            case 1: {
                setPivotX(rectPoint1.centerX());
                setPivotY(rectPoint1.centerY());
                break;
            }

            // Set Point 2 as pivot
            case 2: {
                setPivotX(rectPoint2.centerX());
                setPivotY(rectPoint2.centerY());
                break;
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        float width = getWidth();
        float height = getHeight();

        //Draw line between anchor points
        canvas.drawLine(
                rectPoint1.centerX(), rectPoint1.centerY(),
                rectPoint2.centerX(), rectPoint2.centerY(), paint);

        //Draw anchor circle
        canvas.drawCircle(rectPoint1.centerX(), rectPoint1.centerY(), RADIUS, paint);
        canvas.drawCircle(rectPoint2.centerX(), rectPoint2.centerY(), RADIUS, paint);

        //Draw bounding rect
        canvas.drawRect(OFFSET, OFFSET, width - OFFSET, height - OFFSET, paint);

        // Draw anchors label
        canvas.drawText(&quot;1&quot;, rectPoint1.centerX(), rectPoint1.centerY(), paint);
        canvas.drawText(&quot;2&quot;, rectPoint2.centerX(), rectPoint2.centerY(), paint);

        // Draw small circle at the center
        canvas.drawCircle(width/2f, height/2f, 4, paint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        //Recompute anchors rect
        rectPoint1.set(
                OFFSET, h /2f - RADIUS + OFFSET,
                2*RADIUS, h /2f + RADIUS - OFFSET
        );

        rectPoint2.set(
                w - 2*RADIUS, h /2f - RADIUS + OFFSET,
                w - OFFSET, h /2f + RADIUS - OFFSET
        );
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Measure exactly
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        setMeasuredDimension(width, height);
    }


    public void reset() {
        setPivotPoint(0);

        setRotation(0);

        setX(200);
        setY(400);
    }
}

// FixedPosLayout.java

public class FixedPosLayout extends ViewGroup {

    public FixedPosLayout(Context context) {
        super(context);
    }

    public FixedPosLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FixedPosLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int count = getChildCount();

        for (int i = 0; i&lt;count; ++i) {
            View child = getChildAt(i);

            FixedPosLayout.LayoutParams params =
                    (FixedPosLayout.LayoutParams) child.getLayoutParams();

            int left = params.x;
            int top = params.y;

            child.layout(left, top,
                    left + child.getMeasuredWidth(),
                    top + child.getMeasuredHeight());
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Measure this view
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // Measure children
        int count = getChildCount();
        for (int i = 0; i&lt;count; ++i) {
            View child = getChildAt(i);

            FixedPosLayout.LayoutParams lp =
                    (FixedPosLayout.LayoutParams) child.getLayoutParams();

            int childWidthMeasureSpec =
                    MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);

            int childHeightMeasureSpec =
                    MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);

            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        }
    }

    public static class LayoutParams extends ViewGroup.LayoutParams {
        public int x;
        public int y;

        public LayoutParams(int x, int y, int width, int height) {
            super(width, height);
            this.x = x;
            this.y = y;
        }
    }
}

activity_main.xml

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
    xmlns:tools=&quot;http://schemas.android.com/tools&quot;
    tools:context=&quot;.MainActivity&quot;
    android:layout_height=&quot;match_parent&quot;
    android:layout_width=&quot;match_parent&quot;&gt;

    &lt;com.abdo.rotateviewquestion.FixedPosLayout
        android:layout_width=&quot;0dp&quot;
        android:layout_height=&quot;0dp&quot;
        android:id=&quot;@+id/fixedPosLayout&quot;
        app:layout_constraintStart_toStartOf=&quot;parent&quot;
        app:layout_constraintEnd_toEndOf=&quot;parent&quot;
        app:layout_constraintTop_toTopOf=&quot;parent&quot;
        app:layout_constraintBottom_toTopOf=&quot;@id/barrier_horizontal_top&quot;/&gt;
    
    &lt;ImageButton
        android:id=&quot;@+id/moveRightButton&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:src=&quot;@drawable/move_right&quot;
        app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
        app:layout_constraintStart_toEndOf=&quot;@+id/barrier_vertical_right&quot;/&gt;

    &lt;ImageButton
        android:id=&quot;@+id/moveLeftButton&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:src=&quot;@drawable/move_left&quot;
        app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
        app:layout_constraintStart_toStartOf=&quot;parent&quot;
        app:layout_constraintEnd_toStartOf=&quot;@id/barrier_vertical_left&quot;/&gt;

    &lt;ImageButton
        android:id=&quot;@+id/moveUpButton&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:src=&quot;@drawable/move_up&quot;
        app:layout_constraintBottom_toTopOf=&quot;@+id/moveBottomButton&quot;
        app:layout_constraintEnd_toEndOf=&quot;@id/moveBottomButton&quot;
        app:layout_constraintStart_toStartOf=&quot;@id/moveBottomButton&quot; /&gt;

    &lt;ImageButton
        android:id=&quot;@+id/moveBottomButton&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:src=&quot;@drawable/move_down&quot;
        app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
        app:layout_constraintStart_toEndOf=&quot;@+id/moveLeftButton&quot;/&gt;

    &lt;ImageButton
        android:id=&quot;@+id/rotateLeftButton&quot;
        android:layout_width=&quot;70dp&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:src=&quot;@drawable/rotate_left&quot;
        app:layout_constraintEnd_toEndOf=&quot;parent&quot;
        app:layout_constraintBottom_toBottomOf=&quot;parent&quot; /&gt;
    
    &lt;ImageButton
        android:id=&quot;@+id/rotateRightButton&quot;
        android:layout_width=&quot;70dp&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:src=&quot;@drawable/rotate_right&quot;
        app:layout_constraintEnd_toStartOf=&quot;@id/rotateLeftButton&quot;
        app:layout_constraintBottom_toBottomOf=&quot;parent&quot; /&gt;
    
    &lt;Spinner
        android:id=&quot;@+id/pivotPointSpinner&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        app:layout_constraintEnd_toEndOf=&quot;parent&quot;
        app:layout_constraintTop_toBottomOf=&quot;@id/barrier_horizontal_top&quot;/&gt;

    &lt;androidx.appcompat.widget.AppCompatButton
        android:id=&quot;@+id/resetButton&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:text=&quot;Reset&quot;
        app:layout_constraintTop_toBottomOf=&quot;@id/barrier_horizontal_top&quot;
        app:layout_constraintEnd_toStartOf=&quot;@id/pivotPointSpinner&quot;/&gt;

    &lt;androidx.constraintlayout.widget.Barrier
        android:id=&quot;@+id/barrier_vertical_right&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        app:barrierDirection=&quot;right&quot;
        app:constraint_referenced_ids=&quot;moveUpButton, moveBottomButton&quot;/&gt;


    &lt;androidx.constraintlayout.widget.Barrier
        android:id=&quot;@+id/barrier_vertical_left&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        app:barrierDirection=&quot;left&quot;
        app:constraint_referenced_ids=&quot;moveUpButton, moveBottomButton&quot;/&gt;

    &lt;androidx.constraintlayout.widget.Barrier
        android:id=&quot;@+id/barrier_horizontal_top&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        app:barrierDirection=&quot;top&quot;
        app:constraint_referenced_ids=&quot;moveUpButton, rotateLeftButton, rotateRightButton&quot;/&gt;
    
&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;

答案1

得分: 2

原因:

> setRotation
> 设置视图围绕中心点旋转的度数。增加的值会导致顺时针旋转。

文档 表示旋转围绕中心点发生变化;所以当你在修改中心点之前改变旋转时,旋转会考虑原始中心点;然后在你修改中心点之后,旋转仍然考虑原始中心点;因此你会看到视图跳动。

此外,如果屏幕坐标与中心点不同,改变视图的 pivotX/pivotY 值会改变视图在屏幕上的位置。这个回答有一个很好的 解释。所以在初始旋转的情况下,你不会注意到变化,因为此时中心点与屏幕坐标相同。但是,当视图被旋转时情况就不同了。

解决方案:

因此,一个简单的解决方案是获取修改中心点之前和之后的视图位置的差异;然后用这个差异重新定位视图的 x/y 位置:

String TAG = &quot;LOG_TAG&quot;;

public void setPivotPoint(int position) {

	// 获取视图在屏幕上的位置
	int[] locationBefore = new int[2];
	getLocationOnScreen(locationBefore);
	Log.d(TAG, &quot;\ngetLocationOnScreen: x = &quot; + locationBefore[0] + &quot; y = &quot; + locationBefore[1]);

	switch (position) {
		// 将中心点设置为中心点
		case 0: {
			float width = getWidth();
			float height = getHeight();
			setPivotX(width / 2);
			setPivotY(height / 2);
			break;
		}

		// 将点1设置为中心点
		case 1: {
			setPivotX(rectPoint1.centerX());
			setPivotY(rectPoint1.centerY());
			break;
		}

		// 将点2设置为中心点
		case 2: {
			setPivotX(rectPoint2.centerX());
			setPivotY(rectPoint2.centerY());
			break;
		}
	}

	// 修改了 pivotX 和 pivotY 后获取视图在屏幕上的新位置
	int[] locationAfter = new int[2];
	getLocationOnScreen(locationAfter);
	Log.d(TAG, &quot;getLocationOnScreen: x = &quot; + locationAfter[0] + &quot; y = &quot; + locationAfter[1]);

	// 将视图的当前位置还原到原始位置
	int xDiff = locationAfter[0] - locationBefore[0];
	setX(getX() - xDiff);
	int yDiff = locationAfter[1] - locationBefore[1];
	setY(getY() - yDiff);

	// 检查新位置
	getLocationOnScreen(locationAfter);
	Log.d(TAG, &quot;getLocationOnScreen: x = &quot; + locationAfter[0] + &quot; y = &quot; + locationAfter[1]);

}

预览:

自定义视图位置在更改枢轴点时跳跃的问题。

英文:

Cause:

> setRotation
> Sets the degrees that the view is rotated around the pivot point. Increasing values result in clockwise rotation.

The documentation says that the rotation changes around the pivot point; so when you change the rotation before modifying the pivot point, the rotation considered the original pivot point; then after you modify the pivot, still the rotation considers the original pivot; and therefore you'd see the view jumps.

In addition, changing the pivotX/pivotY values of a view would change the view position on the screen in case that the screen coordinates are different than the pivot point. This answer has a nice breakdown for that. So, you'd not notice a change for the initial rotation because in that case the pivot point are the same as the screen coordinates. But, that will not be the case when the view is rotated.

Solution:

So, one simple solution is to get the difference between the view location before and after modifying the pivot; and relocate the view position x/y with that difference:

String TAG = &quot;LOG_TAG&quot;;
public void setPivotPoint(int position) {
// Get the location of the View on the screen
int[] locationBefore = new int[2];
getLocationOnScreen(locationBefore);
Log.d(TAG, &quot;\ngetLocationOnScreen: x = &quot; + locationBefore[0] + &quot; y = &quot; + locationBefore[1]);
switch (position) {
// Set center point as pivot
case 0: {
float width = getWidth();
float height = getHeight();
setPivotX(width / 2);
setPivotY(height / 2);
break;
}
// Set Point 1 as pivot
case 1: {
setPivotX(rectPoint1.centerX());
setPivotY(rectPoint1.centerY());
break;
}
// Set Point 2 as pivot
case 2: {
setPivotX(rectPoint2.centerX());
setPivotY(rectPoint2.centerY());
break;
}
}
// Get the new location of the View on the screen after changing the pivotX &amp; pivotY
int[] locationAfter = new int[2];
getLocationOnScreen(locationAfter);
Log.d(TAG, &quot;getLocationOnScreen: x = &quot; + locationAfter[0] + &quot; y = &quot; + locationAfter[1]);
// Change the current location of the View back to the original location
int xDiff = locationAfter[0] - locationBefore[0];
setX(getX() - xDiff);
int yDiff = locationAfter[1] - locationBefore[1];
setY(getY() - yDiff);
// Checking the new location
getLocationOnScreen(locationAfter);
Log.d(TAG, &quot;getLocationOnScreen: x = &quot; + locationAfter[0] + &quot; y = &quot; + locationAfter[1]);
}

Preview:

自定义视图位置在更改枢轴点时跳跃的问题。

huangapple
  • 本文由 发表于 2023年8月5日 09:18:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76839786.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定