Java 如何在android中使用句柄缩放视图?

Java 如何在android中使用句柄缩放视图?,java,android,android-widget,android-imageview,android-view,Java,Android,Android Widget,Android Imageview,Android View,我正在尝试在android中实现一个句柄来缩放视图。我不想使用像多点触控这样的东西,而是希望能够用一个手指调整图像的大小 这是我的活动代码。我觉得我很接近有五件事不能正常工作 除垢器已关闭。它的增长速度比它应该的要快得多已解决谢谢@Salauyou 视图只会增长,而不会收缩已解决谢谢@Salauyou 控制柄视图不随图像移动已解决谢谢@Salauyou 缩放开始时非常小已解决谢谢@Salauyou 把手没有完全沿着你的手指 我正在寻找任何可以实现这样一个功能的帮助。无论它是一个库,还是有人可以帮

我正在尝试在android中实现一个句柄来缩放视图。我不想使用像多点触控这样的东西,而是希望能够用一个手指调整图像的大小

这是我的活动代码。我觉得我很接近有五件事不能正常工作

  • 除垢器已关闭。它的增长速度比它应该的要快得多已解决谢谢@Salauyou
  • 视图只会增长,而不会收缩已解决谢谢@Salauyou
  • 控制柄视图不随图像移动已解决谢谢@Salauyou
  • 缩放开始时非常小已解决谢谢@Salauyou
  • 把手没有完全沿着你的手指
  • 我正在寻找任何可以实现这样一个功能的帮助。无论它是一个库,还是有人可以帮助我编写我已有的代码。我发现了一个库,它可以帮助多点触摸缩放图像(),但我能找到的唯一指针是如何实现缩放的增加。这必须通过使用两个点来完成,并找到它们之间的距离

    我的java活动:

    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() {
    
                int[] touchPoint = new int[2];
                int[] centerOfImage = new int[2];
    
                double originalDistance = 0;
                double modifiedDistance = 0;
    
                float originalScale = 0;
                float modifiedScale = 0;
    
                public boolean onTouch(View v, MotionEvent motionEvent) {
    
                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
    
                        centerOfImage[0] = (int) (imageView.getX() + imageView.getWidth() / 2);
                        centerOfImage[1] = (int) (imageView.getY() + imageView.getHeight() / 2);
    
                        touchPoint[0] = (int) motionEvent.getRawX();
                        touchPoint[1] = (int) motionEvent.getRawY();
    
                        int[] p = new int[2];
                        p[0] = touchPoint[0] - centerOfImage[0];
                        p[1] = touchPoint[1] - centerOfImage[1];
    
                        originalDistance = (float) Math.sqrt(p[0] * p[0] + p[1] * p[1]);
                        originalScale = imageView.getScaleX();
    
                    } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
                        touchPoint[0] = (int) motionEvent.getRawX();
                        touchPoint[1] = (int) motionEvent.getRawY();
    
                        int[] p = new int[2];
                        p[0] = (touchPoint[0] + p[0] - centerOfImage[0]);
                        p[1] = (touchPoint[1] + p[1] - centerOfImage[1]);
                        modifiedDistance = Math.hypot(touchPoint[0] - centerOfImage[0], touchPoint[1] - centerOfImage[1]);
    
                        Log.e("resize", "original " + imageView.getWidth() + " modified: " + imageView.getHeight());
                        modifiedScale = (float) (modifiedDistance / originalDistance * originalScale);
    
                        imageView.setScaleX(modifiedScale);
                        imageView.setScaleY(modifiedScale);
    
                        dragHandle.setX(centerOfImage[0] + imageView.getWidth()/2 * modifiedScale);
                        dragHandle.setY(centerOfImage[1] + imageView.getHeight()/2 * modifiedScale);
    
                    } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
    
                    }
                    return true;
                }
            });
        }
    }
    
    我的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/dragArrow" />
    
        </RelativeLayout>
    
    </RelativeLayout>
    
    
    

    所以。。。主要问题是
    getRawX()
    getRawY()
    运动事件的
    MotionEvent
    方法提供绝对屏幕坐标,而
    getX()
    getY()
    提供布局坐标。因此,进度条和状态条的高度不同,所以在获取触摸坐标时,我们应该相对于布局重新计算它们

    dragHandle.setOnTouchListener(new View.OnTouchListener() {
    
        float centerX, centerY, startR, startScale, startX, startY;
    
        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();
    
            } 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);
    
            } else if (e.getAction() == MotionEvent.ACTION_UP) {
    
            }
            return true;
        }
    });
    

    此外,我用库方法替换了假设计算,并将所有坐标声明为浮点,以避免不必要的投射。

    有没有不使用的原因?我不认为我需要的是附件缩放控件。抱歉,句柄视图不随图像移动。因为它不应该。您的大图像被视为容器的原始大小,因为
    setScaleX()
    和其他变换方法只影响视图的绘制,而不影响视图在布局中的空间。
    Math.sqrt(p[0]*p[0]+p[1]*p[1])
    可以轻松地被
    Math.hypot(p[0],p[1])
    取代,更具可读性,精确而有效。所以比例不会改变大小@Salauyou?这很有效。我现在需要旋转和缩放,但在结合这两个方面时,我遇到了一个问题。是否要通过拖动一个处理程序同时执行两个操作?是。我曾经在iOS上看到一个应用程序可以做到这一点。它工作得很好,但我不记得它的名字了。我希望它能像“收缩到缩放”一样工作。如果按住以缩放,也可以同时旋转。是的,一次两个操作。那么你想捏缩放/旋转(使用两个手指)还是拖动缩放/旋转(使用一个手指和处理程序图标)?方法和解决办法将有所不同。