如何在同一视图上实现触摸监听器和双指缩放?

3
我希望您能实现触摸监听器以移动视图并使用捏合缩放来进行缩放,但当我用手指触摸视图进行捏合缩放时,只有触摸监听器起作用。我无法正确处理捏合缩放。请帮助我,因为我不知道如何实现这一点。我已经尝试了所有方法,但无法解决这个问题。
xml:
    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher_foreground" />

Java代码:

public class ExperimentActivity extends AppCompatActivity {

    private static final String TAG = ExperimentActivity.class.getSimpleName();

    LinearLayout mRootView;
    ImageView mImageView;

    private ScaleGestureDetector mScaleGestureDetector;
    private float mScaleFactor = 1.0f;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_experiment);

        mRootView = findViewById(R.id.rootView);
        mImageView = findViewById(R.id.image_view);
        mImageView.setOnTouchListener(onTouchListener());
        mScaleGestureDetector = new ScaleGestureDetector(ExperimentActivity.this, new ScaleListener());
    }

    public boolean onTouchEvent(MotionEvent motionEvent) {
        mScaleGestureDetector.onTouchEvent(motionEvent);
        return true;
    }

    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        @Override
        public boolean onScale(ScaleGestureDetector scaleGestureDetector){
            mScaleFactor *= scaleGestureDetector.getScaleFactor();
            mScaleFactor = Math.max(0.5f, Math.min(mScaleFactor, 1.1f));
            int w = (int) (mImageView.getWidth() * mScaleFactor);
            int h = (int) (mImageView.getHeight() * mScaleFactor);
            w = Math.min(450, Math.max(80, w));
            h = Math.min(450, Math.max(80, h));
            mImageView.setLayoutParams(new LinearLayout.LayoutParams(w, h));
            return true;
        }
    }

    private View.OnTouchListener onTouchListener() {
        return new View.OnTouchListener() {

            @SuppressLint("ClickableViewAccessibility")
            float dX, dY;
            int lastAction;

            @Override
            public boolean onTouch(View view, MotionEvent event) {

                switch (event.getActionMasked()) {
                    case MotionEvent.ACTION_DOWN:
                        dX = view.getX() - event.getRawX();
                        dY = view.getY() - event.getRawY();
                        lastAction = MotionEvent.ACTION_DOWN;
                        break;

                    case MotionEvent.ACTION_MOVE:
                        view.setY(event.getRawY() + dY);
                        view.setX(event.getRawX() + dX);
                        lastAction = MotionEvent.ACTION_MOVE;
                        break;

                    case MotionEvent.ACTION_UP:
                        if (lastAction == MotionEvent.ACTION_DOWN)
                            Toast.makeText(ExperimentActivity.this, "Clicked!", Toast.LENGTH_SHORT).show();
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        dX = view.getX() - event.getRawX();
                        dY = view.getY() - event.getRawY();
                        lastAction = MotionEvent.ACTION_POINTER_DOWN;
                        mScaleGestureDetector = new ScaleGestureDetector(ExperimentActivity.this, new ScaleListener());
                        break;
                    default:
                        return false;
                }
                return true;
            }
        };
    }

}
1个回答

2

尝试按照以下方式更新您的代码。

public class ExperimentActivity extends AppCompatActivity {

private static final String TAG = ExperimentActivity.class.getSimpleName();

LinearLayout mRootView;
ImageView mImageView;

private ScaleGestureDetector mScaleGestureDetector;
private float mScaleFactor = 1.0f;
private Handler mHandler;
private boolean pinchToZoom;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);

    mHandler = new Handler();
    mRootView = findViewById(R.id.rootView);
    mImageView = findViewById(R.id.image_view);
    mImageView.setOnTouchListener(onTouchListener());
    mScaleGestureDetector = new ScaleGestureDetector(ExperimentActivity.this, new ScaleListener());
}

public boolean onTouchEvent(MotionEvent motionEvent) {
    mScaleGestureDetector.onTouchEvent(motionEvent);
    return true;
}

private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    @Override
    public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
        mScaleFactor *= scaleGestureDetector.getScaleFactor();
        mScaleFactor = Math.max(0.5f, Math.min(mScaleFactor, 2.0f));
        int w = (int) (mImageView.getWidth() * mScaleFactor);
        int h = (int) (mImageView.getHeight() * mScaleFactor);
        w = Math.min(900, Math.max(80, w));
        h = Math.min(900, Math.max(80, h));
        mImageView.setLayoutParams(new LinearLayout.LayoutParams(w, h));

        return true;
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        pinchToZoom = true;
        return super.onScaleBegin(detector);
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
        resetFlag();
        super.onScaleEnd(detector);
    }
}

private void resetFlag() {
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            pinchToZoom = false;
        }
    }, 500);
}

private View.OnTouchListener onTouchListener() {
    return new View.OnTouchListener() {
        float dX, dY;
        int lastAction;

        @Override
        public boolean onTouch(View view, MotionEvent event) {

            switch (event.getActionMasked()) {

                case MotionEvent.ACTION_DOWN:
                    dX = view.getX() - event.getRawX();
                    dY = view.getY() - event.getRawY();
                    lastAction = MotionEvent.ACTION_DOWN;
                    break;

                case MotionEvent.ACTION_MOVE:
                    onTouchEvent(event);
                    if (!pinchToZoom) {
                        view.setY(event.getRawY() + dY);
                        view.setX(event.getRawX() + dX);
                        lastAction = MotionEvent.ACTION_MOVE;
                    }
                    break;

                case MotionEvent.ACTION_UP:
                    mHandler.removeCallbacksAndMessages(null);
                    pinchToZoom = false;
                    break;

                case MotionEvent.ACTION_POINTER_DOWN:
                    dX = view.getX() - event.getRawX();
                    dY = view.getY() - event.getRawY();
                    lastAction = MotionEvent.ACTION_POINTER_DOWN;
                    break;
                default:
                    return false;
            }
            return true;
        }
    };
}

1
我几乎尝试了相同的答案,但不同之处在于你在onScale()方法中有mScaleFactor *= detector.getScaleFactor();。所以,基本上对我来说*=起作用了。谢谢。 - Vivek Thummar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接