Android SDK中 - 不结垢,在触摸的中心 [英] Android SDK - Not Scaling at Centre of Touch

查看:138
本文介绍了Android SDK中 - 不结垢,在触摸的中心的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小问题,我的应用程序。我刚才已经实现双指缩放,但是当我捏放大,图像不以规模为显示在下面的图像的2点的中心。图片1是我的手指捏着前和图像2是显示它没有向外扩展在我的手指中心像它应该。

I have a little problem with my app. I have just implemented pinch zoom, but when I pinch to zoom, the image does not scale at the centre of the 2 points as displayed in the images below. Image 1 is where my fingers are before pinching and image 2 is to display that it has not scaled out at the centre of my fingers like it should.

图片1对图2:

Image 1 vs Image 2:

下面是我的code:

        package com.jpiionefourone.guitarimage;

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.drawable.Drawable;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.ScaleGestureDetector;
    import android.view.View;

    public class MultiTouchView extends View {
        private Drawable mIcon;
        private float mPosX;
        private float mPosY;

        private float mLastTouchX;
        private float mLastTouchY;

        private static final int INVALID_POINTER_ID = -1;

        // The ‘active pointer’ is the one currently moving our object.
        private int mActivePointerId = INVALID_POINTER_ID;

        private ScaleGestureDetector mScaleDetector;
        private float mScaleFactor = 1.f;


        public MultiTouchView(Context context) {
            this(context, null, 0);
        }

        public MultiTouchView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }

        public MultiTouchView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            mIcon = context.getResources().getDrawable(R.drawable.guitar);
            mIcon.setBounds(0, 0, mIcon.getIntrinsicWidth(), mIcon.getIntrinsicHeight());

            // Create our ScaleGestureDetector
            mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());

        }

        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            // Let the ScaleGestureDetector inspect all events.
            mScaleDetector.onTouchEvent(ev);

            final int action = ev.getAction();
            switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: {
                final float x = ev.getX();
                final float y = ev.getY();

                mLastTouchX = x;
                mLastTouchY = y;
                mActivePointerId = ev.getPointerId(0);
                break;
            }

            case MotionEvent.ACTION_MOVE: {
                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                final float x = ev.getX(pointerIndex);
                final float y = ev.getY(pointerIndex);

                // Only move if the ScaleGestureDetector isn't processing a gesture.
                if (!mScaleDetector.isInProgress()) {
                    final float dx = x - mLastTouchX;
                    final float dy = y - mLastTouchY;

                    mPosX += dx;
                    mPosY += dy;

                    invalidate();
                }

                mLastTouchX = x;
                mLastTouchY = y;

                break;
            }

            case MotionEvent.ACTION_UP: {
                mActivePointerId = INVALID_POINTER_ID;
                break;
            }

            case MotionEvent.ACTION_CANCEL: {
                mActivePointerId = INVALID_POINTER_ID;
                break;
            }

            case MotionEvent.ACTION_POINTER_UP: {
                final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
                        >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                final int pointerId = ev.getPointerId(pointerIndex);
                if (pointerId == mActivePointerId) {
                    // This was our active pointer going up. Choose a new
                    // active pointer and adjust accordingly.
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    mLastTouchX = ev.getX(newPointerIndex);
                    mLastTouchY = ev.getY(newPointerIndex);
                    mActivePointerId = ev.getPointerId(newPointerIndex);
                }
                break;
            }
            }

            return true;
        }

        @Override
        public void onDraw(Canvas canvas) {
            super.onDraw(canvas);

            canvas.save();
            canvas.translate(mPosX, mPosY);
            canvas.scale(mScaleFactor, mScaleFactor);
            mIcon.draw(canvas);
            canvas.restore();
        }

        private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                mScaleFactor *= detector.getScaleFactor();

                // Don't let the object get too small or too large.
                mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));

                invalidate();
                return true;
            }
        }
    }

谢谢

贾里德

推荐答案

在你的 ScaleListener 类,你只能调整 mScaleFactor 所以,实际上,你形象的确会的没有的变焦各地以你为中心的多点触摸手势!

In your ScaleListener class you only adjust mScaleFactor so, indeed, you image will indeed not zoom around the center of you multi-touch gesture!

此外,你需要更新 mPosX mPosY 使用比例不同的中心。

Additionally, you need to update mPosX and mPosY to use a different center of scaling.

有关我自己的应用程序之一,我用的是这样的:

For one of my own applications, I used something like this:

final float scale = detector.getScaleFactor();
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor * scale, 5.0f));

if (mScaleFactor < 5f) {
   // 1 Grabbing
   final float centerX = detector.getFocusX();
   final float centerY = detector.getFocusY();
   // 2 Calculating difference
   float diffX = centerX - mPosX;
   float diffY = centerY - mPosY;
   // 3 Scaling difference
   diffX = diffX * scale - diffX;
   diffY = diffY * scale - diffY;
   // 4 Updating image origin
   mPosX -= diffX;
   mPosY -= diffY;
}

基本上,它由

Basically, it calculates the relative change of the origin of your image by

  1. 抓住你的多点触摸手势的由来( getFocus()
  2. 计算你的形象起源之差( diffX diffY
  3. 应用比例因子
  4. ,并通过使用经缩放的差异更新的图像的原点
  1. grabbing the origin of your multi-touch gesture (getFocus())
  2. calculating the difference between your image origin (diffX and diffY)
  3. applying the scale factor
  4. and updating the origin of the image by using the scaled difference

这(仍)适用于我的情况。我不知道我们是否都使用(四)同一坐标系统,但这样的事情应该可以帮助您在正确的缩放图像的多点触摸手势的中心。

This (still) works for my situation. I do not know whether we both use(d) the same coordinate systems, but something like this should help you in properly scaling the image at the center of the multi-touch gesture.

这篇关于Android SDK中 - 不结垢,在触摸的中心的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆