有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在Android中基于一个句柄旋转和缩放视图

我正在尝试根据Android中的一个“拖动”手柄旋转和缩放视图。随着布局的旋转和视图大小的调整,最终的结果应该是拖动手柄跟随用户的手指移动

这是基于这两个问题的结合:

  1. How to scale a view in 安卓 using a handle?
  2. Rotating around two points in 安卓 not working

唯一似乎有问题的是旋转代码

这是我的活动代码:

public class MainActivity extends Activity {
    ImageView imageView;
    ImageView dragHandle;
    RelativeLayout layout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (ImageView) findViewById(R.id.imageView1);
        imageView.setBackgroundColor(Color.MAGENTA);
        dragHandle = (ImageView) findViewById(R.id.imageView2);
        dragHandle.setBackgroundColor(Color.CYAN);
        layout = (RelativeLayout) findViewById(R.id.relativeLayout2);
        layout.setBackgroundColor(Color.YELLOW);
        setUpResize();

    }

    public void setUpResize() {
        dragHandle.setOnTouchListener(new View.OnTouchListener() {

            float centerX, centerY, startR, startScale, startX, startY;

            float startAngle;
            float zeroAngle;
            int firstPointX;
            int firstPointY;

            public boolean onTouch(View v, MotionEvent e) {

                if (e.getAction() == MotionEvent.ACTION_DOWN) {

                    // calculate center of image
                    centerX = (imageView.getLeft() + imageView.getRight()) / 2f;
                    centerY = (imageView.getTop() + imageView.getBottom()) / 2f;

                    // recalculate coordinates of starting point
                    startX = e.getRawX() - dragHandle.getX() + centerX;
                    startY = e.getRawY() - dragHandle.getY() + centerY;

                    // get starting distance and scale
                    startR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);
                    startScale = imageView.getScaleX();

                    /*
                     * Rotate code
                     */

                    int[] locationOfLayout = new int[2];
                    int[] locationOfDrag = new int[2];

                    layout.getLocationOnScreen(locationOfLayout);
                    dragHandle.getLocationOnScreen(locationOfDrag);

                    firstPointX = locationOfLayout[0];
                    firstPointY = locationOfLayout[1];

                    float secondPointX = e.getRawX();
                    float secondPointY = e.getRawY();

                    zeroAngle = findRotation(firstPointX, firstPointY, secondPointX, secondPointY); // remember
                                                                                                    // "zero"
                                                                                                    // angle
                    startAngle = layout.getRotation(); // remember angle at
                                                        // which layout is
                                                        // rotated at the start

                } else if (e.getAction() == MotionEvent.ACTION_MOVE) {

                    // calculate new distance
                    float newR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);

                    // set new scale
                    float newScale = newR / startR * startScale;
                    imageView.setScaleX(newScale);
                    imageView.setScaleY(newScale);

                    // move handler image
                    dragHandle.setX(centerX + imageView.getWidth() / 2f * newScale);
                    dragHandle.setY(centerY + imageView.getHeight() / 2f * newScale);

                    /*
                     * Rotate code
                     */

                    layout.setRotation(findRotation(firstPointX, firstPointY, e.getRawX(), e.getRawY()) - zeroAngle
                            + startAngle); // rotate relative to start and zero
                                            // angle

                } else if (e.getAction() == MotionEvent.ACTION_UP) {

                }
                return true;
            }
        });
    }

    private float findRotation(float firstPointX, float firstPointY, float secondPointX, float secondPointY) {
        double delta_x = (secondPointX - firstPointX);
        double delta_y = (secondPointY - firstPointY);
        double radians = Math.atan2(delta_y, delta_x);
        return (float) Math.toDegrees(radians);
    }
}

xml:

<RelativeLayout xmlns:安卓="http://schemas.安卓.com/apk/res/安卓"
    xmlns:tools="http://schemas.安卓.com/tools"
    安卓:layout_width="match_parent"
    安卓:layout_height="match_parent" >

    <RelativeLayout
        安卓:id="@+id/relativeLayout2"
        安卓:layout_width="match_parent"
        安卓:layout_height="match_parent"
        安卓:layout_centerInParent="true" >

        <ImageView
            安卓:id="@+id/imageView1"
            安卓:layout_width="wrap_content"
            安卓:layout_height="wrap_content"
            安卓:layout_centerHorizontal="true"
            安卓:layout_centerVertical="true"
            安卓:src="@drawable/ic_launcher" />

        <ImageView
            安卓:id="@+id/imageView2"
            安卓:layout_width="20dp"
            安卓:layout_height="20dp"
            安卓:layout_below="@+id/imageView1"
            安卓:layout_toRightOf="@+id/imageView1"
            安卓:src="@drawable/meanicons" />

    </RelativeLayout>

</RelativeLayout>

共 (1) 个答案

  1. # 1 楼答案

    如果需要使用一个处理程序图标同时调整图像大小和旋转图像,则应执行一些三角计算

    根据图像的初始角度和连接图像中心和当前手指位置的向量旋转的角度,计算图像旋转的角度并不困难。更复杂一点的任务是将处理程序放置在屏幕的适当位置,使其始终连接主图像的一角

    public void setUpResize() {
        dragHandle.setOnTouchListener(new View.OnTouchListener() {
    
            float centerX, centerY, startR, startScale, startX, startY, startRotation, startA ;
    
            public boolean onTouch(View v, MotionEvent e) {
    
                if (e.getAction() == MotionEvent.ACTION_DOWN) {
    
                    centerX = (imageView.getLeft() + imageView.getRight()) / 2f;
                    centerY = (imageView.getTop() + imageView.getBottom()) / 2f;
    
                    startX = e.getRawX() - dragHandle.getX() + centerX;
                    startY = e.getRawY() - dragHandle.getY() + centerY; 
    
                    startR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);
                    startA = (float) Math.toDegrees(Math.atan2(e.getRawY() - startY, e.getRawX() - startX));
    
                    startScale = imageView.getScaleX();
                    startRotation = imageView.getRotation();
    
                } else if (e.getAction() == MotionEvent.ACTION_MOVE) {
    
                    float newR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);
                    float newA = (float) Math.toDegrees(Math.atan2(e.getRawY() - startY, e.getRawX() - startX));
                    float newScale = newR / startR * startScale;
                    float newRotation = newA - startA + startRotation;
    
                    imageView.setScaleX(newScale);
                    imageView.setScaleY(newScale);
                    imageView.setRotation(newRotation);
    
    
                    //   - this part takes some effort to understand...    
                    dragHandle.setX((float) (centerX + Math.hypot(imageView.getWidth(), imageView.getHeight())/2f * newScale 
                            * Math.cos(Math.toRadians(newRotation) + Math.atan2(imageView.getHeight(), imageView.getWidth()))));
    
                    dragHandle.setY((float) (centerY + Math.hypot(imageView.getWidth(), imageView.getHeight())/2f * newScale 
                            * Math.sin(Math.toRadians(newRotation) + Math.atan2(imageView.getHeight(), imageView.getWidth()))));
                    //                             -
    
                    dragHandle.setPivotX(0);
                    dragHandle.setPivotY(0);
                    dragHandle.setRotation(newRotation);
    
    
                } else if (e.getAction() == MotionEvent.ACTION_UP) {
    
                }
                return true;
            }
        });
    }
    

    那么,我在做什么

    Math.hypot(imageView.getWidth(), imageView.getHeight()) / 2f * newScale
    

    这将计算主图像对角线的一半长度,即其中心和角点之间的距离

    Math.atan2(imageView.getHeight(), imageView.getWidth())
    

    这是对角线最初旋转的角度(因为图像不能是正方形,所以这个角度并不总是45度。)

    Math.cos(Math.toRadians(newRotation) + Math.atan2(imageView.getHeight(), imageView.getWidth()))
    

    这给了我们单位向量X轴上的投影,旋转角度由图像旋转的角度和对角线的初始旋转角度组成。将其乘以对角线长度的一半,我们得到图像角点的X

    与Y相同,但使用sin而不是cos