简体   繁体   English

如何在ImageView中在Android中将OnTouchEvent坐标转换/缩放到位图画布上

[英]How to translate/scale OnTouchEvent coordinates onto bitmap canvas in Android in ImageView

I'm trying to set an OnTouchListener to an ImageView on which I'm doing a lot of custom drawing. 我正在尝试将OnTouchListener设置为要执行大量自定义绘图的ImageView。 Problem: my X values are off and I'm constantly registering the touches too far to the left. 问题:我的X值不可用,并且我不断地将触摸记录在左边。 The Y values are ok though, so where is the problem in my algorithm? Y值还可以,所以我算法的问题在哪里?

The canvas I'm using is 400 pixels wide and 300 pixels high. 我正在使用的画布是400像素宽和300像素高。 I'm not applying any special scaling to the ImageView, I'm just relying on the standard ImageView behavior by which it will scale itself to fit the screen. 我没有对ImageView进行任何特殊缩放,我只是依赖于标准ImageView行为,它将根据自身行为进行缩放以适合屏幕。 Little green dots should be appearing where the user touches the screen, but they are instead too far to the left on my Nexus 5. How is it that my math is correct for the Y values, but wrong on the X values? 用户触摸屏幕的地方应该会出现小绿点,但它们在Nexus 5上的位置离左侧太远了。我的数学对Y值正确但对X值错误吗? I'm requesting both the x scale and the y scale, so even if the ImageView is changing the aspect ratio, I should be accounting for that, right? 我同时要求x比例尺和y比例尺,因此即使ImageView更改了宽高比,我也应该考虑这一点,对吗?

public class FullscreenActivity extends AppCompatActivity {

    private ImageView drawingImageView;
    private Canvas canvas;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        int mUIFlag = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LOW_PROFILE
                | View.SYSTEM_UI_FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
        getWindow().getDecorView().setSystemUiVisibility(mUIFlag);
        setContentView(R.layout.activity_fullscreen);

        drawingImageView = (ImageView) this.findViewById(R.id.game_map_fixed_id);
        Bitmap bitmap = Bitmap.createBitmap(Map.width, Map.height, Bitmap.Config.ARGB_8888);
        canvas = new Canvas(bitmap);
        drawingImageView.setImageBitmap(bitmap);
        drawingImageView.setOnTouchListener(mapOnTouchListener);
    }

    View.OnTouchListener mapOnTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            float[] bounds = new float[6];
            bounds = getBitmapPositionInsideImageView(drawingImageView);

            float x = event.getX() / bounds[4] - bounds[0];
            float y = event.getY() / bounds[5] - bounds[1];

            Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
            paint.setColor(Color.GREEN);
            canvas.drawCircle(x, y, 1, paint);
            return false;
        }
    };

    public static float[] getBitmapPositionInsideImageView(ImageView imageView) {
        float[] rect = new float[6];

        if (imageView == null || imageView.getDrawable() == null)
            return rect;

        // Get image dimensions
        // Get image matrix values and place them in an array
        float[] f = new float[9];
        imageView.getImageMatrix().getValues(f);

        // Extract the scale values using the constants (if aspect ratio maintained, scaleX == scaleY)
        final float scaleX = f[Matrix.MSCALE_X];
        final float scaleY = f[Matrix.MSCALE_Y];

        rect[4] = scaleX;
        rect[5] = scaleY;

        // Get the drawable (could also get the bitmap behind the drawable and getWidth/getHeight)
        final Drawable d = imageView.getDrawable();
        final int origW = d.getIntrinsicWidth();
        final int origH = d.getIntrinsicHeight();

        // Calculate the actual dimensions
        final int actW = Math.round(origW * scaleX);
        final int actH = Math.round(origH * scaleY);

        rect[2] = actW;
        rect[3] = actH;

        // Get image position
        // We assume that the image is centered into ImageView
        int imgViewW = imageView.getWidth();
        int imgViewH = imageView.getHeight();

        float left = (imgViewW - actW)/2;
        float top = (imgViewH - actH)/2;

        rect[0] = left;
        rect[1] = top;

        return rect;
    }
}

The error is in the computation of the points after receiving the information from the getBitmapPositionInsideImageView. 错误在于从getBitmapPositionInsideImageView接收信息后计算点数。

        float x = event.getX() / bounds[4] - bounds[0];
        float y = event.getY() / bounds[5] - bounds[1];

should be 应该

        float x = (event.getX() - bounds[0]) / bounds[4];
        float y = (event.getY() - bounds[1]) / bounds[5];

The reason that I wasn't having any problem on the vertical axis is because the image wasn't receiving any padding at the top or bottom which meant that bounds[5] was always zero, hiding the error in that equation. 我在垂直轴上没有任何问题的原因是因为图像的顶部或底部没有填充,这意味着bounds [5]始终为零,从而将误差隐藏在该方程式中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM