实现双击TouchImageView - 拖动图片现在不起作用

时间:2012-08-29 23:54:31

标签: android imageview ontouchevent ontouchlistener gesturedetector

我有问题。我从这里使用了TouchImageView代码 - https://github.com/MikeOrtiz/TouchImageView。我已经实现了双击功能。它工作正常,但现在我无法在放大图像时拖动它。通过手势缩放(捏缩放)工作正常,我无法在缩放图像上导航。我不知道为什么。这是我的实际代码:

        package com.example.testy;

    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Matrix;
    import android.graphics.PointF;
    import android.util.AttributeSet;
    import android.view.GestureDetector;
    import android.view.GestureDetector.SimpleOnGestureListener;
    import android.view.MotionEvent;
    import android.view.ScaleGestureDetector;
    import android.view.View;
    import android.widget.ImageView;

    public class TouchImageView extends ImageView {

        Matrix matrix = new Matrix();

        // We can be in one of these 3 states
        static final int NONE = 0;
        static final int DRAG = 1;
        static final int ZOOM = 2;
        int mode = NONE;

        // Remember some things for zooming
        PointF last = new PointF();
        PointF start = new PointF();
        float minScale = 1f;
        float maxScale = 3f;
        float[] m;

        float redundantXSpace, redundantYSpace;

        float width, height;
        static final int CLICK = 3;
        float saveScale = 1f;
        float right, bottom, origWidth, origHeight, bmWidth, bmHeight;

        ScaleGestureDetector mScaleDetector;
        GestureDetector gestureDetector;
        Context context;

        public TouchImageView(Context context) {
            super(context);
            sharedConstructing(context);
        }

        public TouchImageView(Context context, AttributeSet attrs) {
            super(context, attrs);
            sharedConstructing(context);
        }

        private void sharedConstructing(Context context) {
            gestureDetector = new GestureDetector(new DoubleTapGestureListener());
            super.setClickable(true);
            this.context = context;
            mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
            matrix.setTranslate(1f, 1f);
            m = new float[9];
            setImageMatrix(matrix);
            setScaleType(ScaleType.MATRIX);

            setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (gestureDetector.onTouchEvent(event)) {
                        return true; // podwojne klikniecie i koniec imprezy
                    }
                    mScaleDetector.onTouchEvent(event);

                    matrix.getValues(m);
                    float x = m[Matrix.MTRANS_X];
                    float y = m[Matrix.MTRANS_Y];
                    PointF curr = new PointF(event.getX(), event.getY());

                    switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        last.set(event.getX(), event.getY());
                        start.set(last);
                        mode = DRAG;
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (mode == DRAG) {
                            float deltaX = curr.x - last.x;
                            float deltaY = curr.y - last.y;
                            float scaleWidth = Math.round(origWidth * saveScale);
                            float scaleHeight = Math.round(origHeight * saveScale);
                            if (scaleWidth < width) {
                                deltaX = 0;
                                if (y + deltaY > 0)
                                    deltaY = -y;
                                else if (y + deltaY < -bottom)
                                    deltaY = -(y + bottom);

                            } else if (scaleHeight < height) {
                                deltaY = 0;
                                if (x + deltaX > 0)
                                    deltaX = -x;
                                else if (x + deltaX < -right)
                                    deltaX = -(x + right);

                            } else {
                                if (x + deltaX > 0)
                                    deltaX = -x;
                                else if (x + deltaX < -right)
                                    deltaX = -(x + right);

                                if (y + deltaY > 0)
                                    deltaY = -y;
                                else if (y + deltaY < -bottom)
                                    deltaY = -(y + bottom);

                            }
                            matrix.postTranslate(deltaX, deltaY);
                            last.set(curr.x, curr.y);
                        }
                        break;

                    case MotionEvent.ACTION_UP:
                        mode = NONE;
                        int xDiff = (int) Math.abs(curr.x - start.x);
                        int yDiff = (int) Math.abs(curr.y - start.y);
                        if (xDiff < CLICK && yDiff < CLICK)
                            performClick();
                        break;

                    case MotionEvent.ACTION_POINTER_UP:
                        mode = NONE;
                        break;
                    }
                    setImageMatrix(matrix);
                    invalidate();
                    return true; // indicate event was handled
                }

            });
        }

        @Override
        public void setImageBitmap(Bitmap bm) {
            super.setImageBitmap(bm);
            if (bm != null) {
                bmWidth = bm.getWidth();
                bmHeight = bm.getHeight();
            }
        }

        public void setMaxZoom(float x) {
            maxScale = x;
        }

        public boolean canScrollHorizontally(int direction) { //used to cooparate with ViewPager
            matrix.getValues(m);
            float x = Math.abs(m[Matrix.MTRANS_X]);
            float scaleWidth = Math.round(origWidth * saveScale);

            if (scaleWidth < width) {
                return false;

            } else {
                if (x - direction <= 0)
                    return false; // reach left edge
                else if (x + width - direction >= scaleWidth)
                    return false; // reach right edge

                return true;
            }
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            width = MeasureSpec.getSize(widthMeasureSpec);
            height = MeasureSpec.getSize(heightMeasureSpec);
            // Fit to screen.
            float scale;
            float scaleX = width / bmWidth;
            float scaleY = height / bmHeight;
            scale = Math.min(scaleX, scaleY);
            matrix.setScale(scale, scale);
            setImageMatrix(matrix);
            saveScale = 1f;

            // Center the image
            redundantYSpace = height - (scale * bmHeight);
            redundantXSpace = width - (scale * bmWidth);
            redundantYSpace /= 2;
            redundantXSpace /= 2;

            matrix.postTranslate(redundantXSpace, redundantYSpace);

            origWidth = width - 2 * redundantXSpace;
            origHeight = height - 2 * redundantYSpace;
            right = width * saveScale - width - (2 * redundantXSpace * saveScale);
            bottom = height * saveScale - height
                    - (2 * redundantYSpace * saveScale);
            setImageMatrix(matrix);
        }

        public boolean isZoomed() {
            return saveScale > minScale;
        }

        public void zoomIn() {

            System.out.println("Zoom in!");

            saveScale = maxScale;
            matrix.setScale(saveScale, saveScale);
            setImageMatrix(matrix);
            invalidate();
        }

        public void zoomOut() {

            saveScale = minScale;
            matrix.setScale(saveScale, saveScale);
            setImageMatrix(matrix);
            invalidate();

            System.out.println("Zoom out!");
        }

        private class DoubleTapGestureListener extends SimpleOnGestureListener {

            @Override
            public boolean onDown(MotionEvent e) {
                return true;
            }

            // event when double tap occurs
            @Override
            public boolean onDoubleTap(MotionEvent e) {
                float x = e.getX();
                float y = e.getY();

                if (isZoomed()) {
                    zoomOut();
                } else {
                    zoomIn();
                }
                return true;
            }

        }

        private class ScaleListener extends
                ScaleGestureDetector.SimpleOnScaleGestureListener {
            @Override
            public boolean onScaleBegin(ScaleGestureDetector detector) {
                mode = ZOOM;
                return true;

            }

            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                float mScaleFactor = detector.getScaleFactor();
                float origScale = saveScale;
                saveScale *= mScaleFactor;
                if (saveScale > maxScale) {
                    saveScale = maxScale;
                    mScaleFactor = maxScale / origScale;
                } else if (saveScale < minScale) {
                    saveScale = minScale;
                    mScaleFactor = minScale / origScale;
                }
                right = width * saveScale - width
                        - (2 * redundantXSpace * saveScale);
                bottom = height * saveScale - height
                        - (2 * redundantYSpace * saveScale);
                if (origWidth * saveScale <= width
                        || origHeight * saveScale <= height) {
                    matrix.postScale(mScaleFactor, mScaleFactor, width / 2,
                            height / 2);
                    if (mScaleFactor < 1) {
                        matrix.getValues(m);
                        float x = m[Matrix.MTRANS_X];
                        float y = m[Matrix.MTRANS_Y];
                        if (mScaleFactor < 1) {
                            if (Math.round(origWidth * saveScale) < width) {
                                if (y < -bottom)
                                    matrix.postTranslate(0, -(y + bottom));
                                else if (y > 0)
                                    matrix.postTranslate(0, -y);
                            } else {
                                if (x < -right)
                                    matrix.postTranslate(-(x + right), 0);
                                else if (x > 0)
                                    matrix.postTranslate(-x, 0);
                            }
                        }
                    }
                } else {
                    matrix.postScale(mScaleFactor, mScaleFactor,
                            detector.getFocusX(), detector.getFocusY());
                    matrix.getValues(m);
                    float x = m[Matrix.MTRANS_X];
                    float y = m[Matrix.MTRANS_Y];
                    if (mScaleFactor < 1) {
                        if (x < -right)
                            matrix.postTranslate(-(x + right), 0);
                        else if (x > 0)
                            matrix.postTranslate(-x, 0);
                        if (y < -bottom)
                            matrix.postTranslate(0, -(y + bottom));
                        else if (y > 0)
                            matrix.postTranslate(0, -y);
                    }
                }
                return true;

            }
    }
}

你有什么问题吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题。这就是我所做的;

  1. 将两个探测器声明在顶部(正如您所做的那样)

    ScaleGestureDetector mScaleDetector;    
    GestureDetector mDoubleTapDetector;
    
  2. 在sharedConstructing(...)中实例化上述变量(正如您所做的那样)

    mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());     
    mDoubleTapDetector = new GestureDetector(context, new DoubleTapListener());
    

    注意:也为GestureDetector提供上下文。

  3. 在onTouch(...)中首先编写以下代码;

    boolean result = mScaleDetector.onTouchEvent(event);                
    // result is always true here, so we need another way to check scalling gesture progress.           
    boolean isScaling = result = mScaleDetector.isInProgress();
    if (!isScaling) {
       // if no scaling is performed check for other gestures (fling, long tab, etc.)
       mDoubleTapDetector.onTouchEvent(event);
    }
    
  4. 添加另一个私有类DoubleTapListener(...)

    private class DoubleTapListener extends GestureDetector.SimpleOnGestureListener{
        @Override
        public boolean onDoubleTap(MotionEvent e) {
        Log.e(TAG,"onDoubleTap");
        return super.onDoubleTap(e);
        }               
    }
    
  5. 就是这样。我希望这会对你有所帮助。