1

我使用以下代码来获得在 ImageView 上工作的图像缩放功能:

@Override
    public boolean onTouch(View v, MotionEvent event) {
        ImageView view = (ImageView) v;
        // Dump touch event to log
        dumpEvent(event);
        // Handle touch events here...
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
        case MotionEvent.ACTION_DOWN:
            savedMatrix.set(matrix);
            start.set(event.getX(), event.getY());
            mode = DRAG;
            break;
        case MotionEvent.ACTION_POINTER_DOWN:
            oldDist = spacing(event);
            if (oldDist > 10f) {
                savedMatrix.set(matrix);
                midPoint(mid, event);
                mode = ZOOM;
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_POINTER_UP:
            mode = NONE;
            break;
        case MotionEvent.ACTION_MOVE:
            if (mode == DRAG) {
                // ...
                matrix.set(savedMatrix);
                matrix.postTranslate(event.getX() - start.x, event.getY()
                        - start.y);
            } else if (mode == ZOOM) {
                float[] f = new float[9];
                matrix.getValues(f);
                float scaleX = f[Matrix.MSCALE_X];
                float scaleY = f[Matrix.MSCALE_Y];

                if (scaleX > MAX_ZOOM || scaleY > MAX_ZOOM || scaleX < MIN_ZOOM
                        || scaleY < MIN_ZOOM) {
                    System.out.println("@@@ true!!!");
                } else {
                    System.out.println("@@@ false!!!");
                    float newDist = spacing(event);
                    if (newDist > 10f) {
                        matrix.set(savedMatrix);
                        float scale = newDist / oldDist;
                        matrix.postScale(scale, scale, mid.x, mid.y);
                    }
                }
            }
            break;
        }

        view.setImageMatrix(matrix);
        return true; // indicate event was handled
    }

    /** Show an event in the LogCat view, for debugging */
    private void dumpEvent(MotionEvent event) {
        String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE",
                "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
        StringBuilder sb = new StringBuilder();
        int action = event.getAction();
        int actionCode = action & MotionEvent.ACTION_MASK;
        sb.append("event ACTION_").append(names[actionCode]);
        if (actionCode == MotionEvent.ACTION_POINTER_DOWN
                || actionCode == MotionEvent.ACTION_POINTER_UP) {
            sb.append("(pid ").append(
                    action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
            sb.append(")");
        }
        sb.append("[");
        for (int i = 0; i < event.getPointerCount(); i++) {
            sb.append("#").append(i);
            sb.append("(pid ").append(event.getPointerId(i));
            sb.append(")=").append((int) event.getX(i));
            sb.append(",").append((int) event.getY(i));
            if (i + 1 < event.getPointerCount())
                sb.append(";");
        }
        sb.append("]");
    }

    /** Determine the space between the first two fingers */
    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return FloatMath.sqrt(x * x + y * y);
    }

    /** Calculate the mid point of the first two fingers */
    private void midPoint(PointF point, MotionEvent event) {
        float x = event.getX(0) + event.getX(1);
        float y = event.getY(0) + event.getY(1);
        point.set(x / 2, y / 2);
    }

我这里有问题。我修改了代码以设置最大放大和缩小限制。我在这里面临的问题是,一旦我达到任何一个限制,因为我在“if”块中什么都没有,图像就会卡住。我应该在这里放什么?

4

3 回答 3

0

如果您使用 ScaleGestureDetector.SimpleOnScaleGestureListener 类,事情会容易得多......

class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {

  public boolean onScale(ScaleGestureDetector detector) {
        //update the current scale  
        scaleFactor *= detector.getScaleFactor();
        if(scaleFactor < MIN_SCALE_FACTOR || scaleFactor > MAX_SCALE_FACTOR){
            scaleFactor = Math.max(MIN_SCALE_FACTOR, 
                                      Math.min(scaleFactor, MAX_SCALE_FACTOR));
        transformMatrix.setScale(scaleFactor, scaleFactor);
    }
}

transformMatrix是 imageview 的图像矩阵;您可以致电imageView.getImageMatrix()保存副本,然后像我一样重新申请transformMatrix.setScale(scaleFactor, scaleFactor)

如果您达到 MAX/MIN 缩放级别,这种方式不会冻结

于 2013-09-23T19:16:50.907 回答
-1

希望这可能对面临同样问题的人有所帮助,此链接上的库帮助我轻松实现了缩放功能:

https://github.com/sephiroth74/ImageViewZoom/blob/master/ImageViewTouchTest/src/it/sephiroth/android/library/imagezoom/test/ImageViewTestActivity.java

于 2013-01-16T05:32:57.380 回答
-2

试试这个代码。使用前请编辑。

public class GuessImageView 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;

    public GuessImageActivity guessImage/* =new GuessImageActivity() */;

    public GuessImageView(Context context) {

        super(context);

        sharedConstructing(context);

    }

    public GuessImageView(Context context, AttributeSet attrs) {

        super(context, attrs);

        sharedConstructing(context);

    }





private void sharedConstructing(Context context) {

        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) {

                mScaleDetector.onTouchEvent(event);

                matrix.getValues(m);
                Log.e("Touch Count","Touch Count"+event.getPointerCount());
//              checkTouchEvent=event.getPointerCount();
                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;
                    isDrag=false;
                    // isDraw=false;

                    break;

                case MotionEvent.ACTION_MOVE:

                    // Log.i("onTouch", "origWidth : " + origWidth +

                    // " origHeight : " + origHeight);

                    if (mode == DRAG) {
Log.d("GuessImage","MODE:Drag");
                        // isDraw=false;

                        float deltaX = curr.x - last.x;

                        float deltaY = curr.y - last.y;

                        scaleWidth = Math.round(origWidth * saveScale);

                        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);

                    }
                    isDrag=true;
                    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) {

                        // isDraw=false;

                        Log.v("ACTION_UP", "ACTION_UP");

                        mPosX = curr.x;

                        mPosY = curr.y;

                        performClick();

//                      if (guessImage.guess_mode) {
                        checkTouchEvent=event.getAction();
                        Log.d("checkTouchEvent",checkTouchEvent+"checkTouchEvent");
                            lastTouchEvent = event.getAction();

                            isDrag=false;
//                      }

//                      else {
//
//                          lastTouchEvent = -1;
//
//                      }

                        // invalidate();

                    }

                    break;

                }

                case MotionEvent.ACTION_POINTER_UP:

                    mode = NONE;

                    break;

                }

                setImageMatrix(matrix);

                scaleWidth = Math.round(origWidth * saveScale);

                scaleHeight = Math.round(origHeight * saveScale);

                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;

    }

    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);

            // mPosX = mPosX + right / saveScale;

            // mPosY = mPosY + bottom / saveScale;

            if (origWidth * saveScale <= width
                    || origHeight * saveScale <= height) {

                float xMove = 0, yMove = 0;

                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));

                                xMove = 0;

                                yMove = -(y + bottom);

                            } else if (y > 0) {

                                matrix.postTranslate(0, -y);

                                xMove = 0;

                                yMove = -y;

                            }

                        } else {

                            if (x < -right) {

                                matrix.postTranslate(-(x + right), 0);

                                xMove = -(x + right);

                                yMove = 0;

                            } else if (x > 0) {

                                matrix.postTranslate(-x, 0);

                                xMove = -(x + right);

                                yMove = 0;

                            }

                        }

                        Log.i("onScale", "mPosX " + mPosX + " mPosX " + mPosX);

                    }

                }

            } else {

                float xMove = 0, yMove = 0;

                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);

                        xMove = -(x + right);

                        yMove = 0;

                    } else if (x > 0) {

                        matrix.postTranslate(-x, 0);

                        xMove = -x;

                        yMove = 0;

                    }

                    if (y < -bottom) {

                        matrix.postTranslate(0, -(y + bottom));

                        xMove = 0;

                        yMove = -(y + bottom);

                    } else if (y > 0) {

                        matrix.postTranslate(0, -y);

                        xMove = 0;

                        yMove = -y;

                    }

                }

                Log.i("onScale", "mPosX " + mPosX + " mPosX " + mPosX);

            }

            return true;

        }

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        if (!isCheckLoadImage) {

            width = MeasureSpec.getSize(widthMeasureSpec);

            height = MeasureSpec.getSize(heightMeasureSpec);

            // Fit to screen.

            float scale;

            float scaleX = (float) width / (float) bmWidth;

            float scaleY = (float) height / (float) bmHeight;

            scale = Math.min(scaleX, scaleY);

            matrix.setScale(scale, scale);

            setImageMatrix(matrix);

            saveScale = 1f;

            // Center the image

            redundantYSpace = (float) height - (scale * (float) bmHeight);

            redundantXSpace = (float) width - (scale * (float) bmWidth);

            redundantYSpace /= (float) 2;

            redundantXSpace /= (float) 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);

        }

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    }

}
于 2013-01-14T06:36:49.817 回答