java - 如何使用句柄在 android 中缩放 View ?

标签 java android android-widget android-imageview android-view

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

这是我的 Activity 代码。我觉得好像我非常接近有五件事不能正常工作。

  1. 缩放已关闭。它的增长速度比应有的快得多。 已解决谢谢@Salauyou
  2. 视野只会扩大,不会缩小。 已解决谢谢@Salauyou
  3. 句柄 View 不随图像移动。 已解决谢谢@Salauyou
  4. 缩放比例开始非常小已解决谢谢@Salauyou
  5. handle 没有完全跟随您的手指。

我正在寻找可以实现此类功能的任何帮助。无论是图书馆还是有人可以帮助我处理我已有的代码。我找到了一个有助于图像多点触控缩放的库 ( https://github.com/brk3/android-multitouch-controller ),但我能找到的唯一指示是如何实现缩放比例的增加。这必须通过使用两个点并找出它们之间的距离来完成。

我的 java Activity :

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>

enter image description here

最佳答案

所以...主要问题是MotionEventgetRawX()getRawY() 方法提供绝对屏幕坐标,而 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;
    }
});

此外,我用库方法替换了 hypothenuse 计算并将所有坐标声明为 float 以避免不必要的转换。

关于java - 如何使用句柄在 android 中缩放 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23092178/

相关文章:

Android:Widget Config Activity 启动两次?

java - 无法解析符号,android studio

javascript - 我正在加载图像而不是 iframe 并使用 jquery 在同一位置播放视频的图像上单击。适用于桌面设备但不适用于移动设备?

android - Spinner 使 Android 应用程序崩溃

android - java.lang.RuntimeException : Handler (android. os.Handler) 向死线程上的 Handler 发送消息

java - Android 如何每隔 x 小时或分钟执行一个方法

android - 如何更改主屏幕小部件中的 TextView 字体样式?

java - 动态生成的 Javascript 输入字段无法被 Httpservletrequest 识别???仅在 Chrome 中?

JavaFX:异常运行 application.main

java - SwingWorker 的基本原理是什么?