旋转以及基于Android中一个把手缩放视图缩放、视图、把手、Android

2023-09-07 22:22:09 作者:好听又温柔的昵称,女生温柔大全

我想旋转和缩放基于Android中一拖手柄的视图。随着布局旋转,视图调整大小,最终的结果应该是拖动手柄跟随用户手指在以往任何时候它的动作。

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

如何利用规模在Android中的视图办理? Rotating围绕两个点的Andr​​oid不工作

这似乎是错误的唯一的事情是旋转code。

3d打印机控制软件下载 3d打印机控制软件 ReplicatorG 下载 v0040中文免费版

下面是我的活动code:

 公共类MainActivity延伸活动{
    ImageView的ImageView的;
    ImageView的dragHandle;
    RelativeLayout的布局;

    @覆盖
    保护无效的onCreate(包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);
        布局=(RelativeLayout的)findViewById(R.id.relativeLayout2);
        layout.setBackgroundColor(Color.YELLOW);
        SETU presize();

    }

    公共无效SETU presize(){
        dragHandle.setOnTouchListener(新View.OnTouchListener(){

            漂浮的centerX,centerY,startR,startScale,STARTX,startY;

            浮动startAngle开始;
            浮动zeroAngle;
            INT firstPointX;
            INT firstPointY;

            公共布尔onTouch(视图V,MotionEvent E){

                如果(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 =(浮点)Math.hypot(e.getRawX() -  STARTX,e.getRawY() -  startY);
                    startScale = imageView.getScaleX();

                    / *
                     *旋转code
                     * /

                    INT [] locationOfLayout =新INT [2];
                    INT [] locationOfDrag =新INT [2];

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

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

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

                    zeroAngle = findRotation(firstPointX,firstPointY,secondPointX,secondPointY); // 记得
                                                                                                    // 零
                                                                                                    // 角度
                    由startAngle = layout.getRotation(); //记得角
                                                        //这布局
                                                        //旋转,在开始

                }否则,如果(e.getAction()== MotionEvent.ACTION_MOVE){

                    //计算新的距离
                    浮动newR =(浮点)Math.hypot(e.getRawX() -  STARTX,e.getRawY() -  startY);

                    //设置新的规模
                    浮newScale = newR / startR * startScale;
                    imageView.setScaleX(newScale);
                    imageView.setScaleY(newScale);

                    //移动处理器的图像
                    dragHandle.setX(的centerX + imageView.getWidth()/ 2F * newScale);
                    dragHandle.setY(centerY + imageView.getHeight()/ 2F * newScale);

                    / *
                     *旋转code
                     * /

                    layout.setRotation(findRotation(firstPointX,firstPointY,e.getRawX(),e.​​getRawY()) -  zeroAngle
                            + startAngle开始); //相对转动启动和零
                                            // 角度

                }否则,如果(e.getAction()== MotionEvent.ACTION_UP){

                }
                返回true;
            }
        });
    }

    私人浮动findRotation(浮firstPointX,浮firstPointY,浮secondPointX,浮secondPointY){
        双delta_x =(secondPointX  -  firstPointX);
        双delta_y =(secondPointY  -  firstPointY);
        双弧度= Math.atan2(delta_y,delta_x);
        返程(浮点)Math.toDegrees(弧度);
    }
}
 

XML:

 < RelativeLayout的的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    的xmlns:工具=htt​​p://schemas.android.com/tool​​s
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent>

    < RelativeLayout的
        机器人:ID =@ + ID / relativeLayout2
        机器人:layout_width =match_parent
        机器人:layout_height =match_parent
        机器人:layout_centerInParent =真正的>

        < ImageView的
            机器人:ID =@ + ID / imageView1
            机器人:layout_width =WRAP_CONTENT
            机器人:layout_height =WRAP_CONTENT
            机器人:layout_centerHorizo​​ntal =真
            机器人:layout_centerVertical =真
            机器人:SRC =@可绘制/ ic_launcher/>

        < ImageView的
            机器人:ID =@ + ID / imageView2
            机器人:layout_width =20dp
            机器人:layout_height =20dp
            机器人:layout_below =@ + ID / imageView1
            机器人:layout_toRightOf =@ + ID / imageView1
            机器人:SRC =@可绘制/ meanicons/>

    < / RelativeLayout的>

< / RelativeLayout的>
 

解决方案

在情况下,你需要调整大小和旋转图像使用一个处理程序图标同时,一些三角函数计算应该执行。

有不是那么难以计算角度通过该图像应被旋转,根据它的初始角度和角度,其中所述载体,连接图像和当前手指位置的中心,转动。一点点更复杂的任务就是定位处理程序在屏幕的适当位置,使之始终连接主图像的角落。

 公共无效SETU presize(){
    dragHandle.setOnTouchListener(新View.OnTouchListener(){

        漂浮的centerX,centerY,startR,startScale,STARTX,startY,startRotation,启动市场;

        公共布尔onTouch(视图V,MotionEvent E){

            如果(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 =(浮点)Math.hypot(e.getRawX() -  STARTX,e.getRawY() -  startY);
                启动市场=(浮点)Math.toDegrees(Math.atan2(e.getRawY() -  startY,e.getRawX() -  STARTX));

                startScale = imageView.getScaleX();
                startRotation = imageView.getRotation();

            }否则,如果(e.getAction()== MotionEvent.ACTION_MOVE){

                浮动newR =(浮点)Math.hypot(e.getRawX() -  STARTX,e.getRawY() -  startY);
                浮动纽瓦=(浮点)Math.toDegrees(Math.atan2(e.getRawY() -  startY,e.getRawX() -  STARTX));
                浮newScale = newR / startR * startScale;
                浮newRotation =纽瓦 ​​- 启动市场+ startRotation;

                imageView.setScaleX(newScale);
                imageView.setScaleY(newScale);
                imageView.setRotation(newRotation);


                // -----这部分需要一些努力来理解------
                dragHandle.setX((浮动)(的centerX + Math.hypot(imageView.getWidth(),imageView.getHeight())/ 2F * newScale
                        * Math.cos(Math.toRadians(newRotation)+ Math.atan2(imageView.getHeight(),imageView.getWidth()))));

                dragHandle.setY((浮动)(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);


            }否则,如果(e.getAction()== MotionEvent.ACTION_UP){

            }
            返回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相同,但使用的罪而不是 COS

I'm trying to rotate and scale a view based on one "drag" handle in Android. With the layout rotating, and the view resizing, the end result should be that the drag handle follows the users finger where ever it moves.

This is based on combining these two questions:

How to scale a view in android using a handle? Rotating around two points in android not working

The only thing that seems wrong is the rotation code.

Here is my activity code:

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:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

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

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

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

    </RelativeLayout>

</RelativeLayout>

解决方案

In case you need to resize and rotate image simultaneously using one handler icon, some trigonometrical calculations should be performed.

It is not so difficult to calculate angle by which image should be rotated, based on its initial angle and angle, by which the vector, that connects center of image and current finger position, is rotated. A little bit more complicated task is to position the handler in a proper place of the screen to make it always connect the corner of main image.

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;
        }
    });
}

So, what I'm doing?

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

--this calculates half length of diagonal of the main image, i. e. distance between its center and corner point

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

--this is angle by which diagonal was rotated initially (since image must not be square, this angle is not always 45 deg.)

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

--this gives us projection onto X axis of unit vector, rotated by an angle composed with angle, at which image is rotated, and angle of initial rotation of its diagonal. After multiplying it to half length of diagonal, we get X of image corner.

The same with Y, but using sin instead of cos.