Android中捏合缩放的比例限制

9
如何设置Pinch-Zoom的最大和最小缩放级别?
这是我的代码: //
public class TouchImageView extends ImageView {

     private static final String TAG = "Touch";

        // These matrices will be used to move and zoom image
        Matrix matrix = new Matrix();
        Matrix savedMatrix = new Matrix();
        static PinchZoomExample sPinchZoomExample = null;
        // 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;
        static Bitmap sCurrentImage;

        // Remember some things for zooming
        PointF start = new PointF();
        PointF mid = new PointF();
        float oldDist = 1f;

        Context context;


        public TouchImageView(Context context) {
            super(context);
            super.setClickable(true);
            this.context = context;

            matrix.setTranslate(1f, 1f);
            setImageMatrix(matrix);
            setScaleType(ScaleType.MATRIX);

            setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent rawEvent) {
                    WrapMotionEvent event = WrapMotionEvent.wrap(rawEvent);

                    // Dump touch event to log
                   /* if (Viewer.isDebug == true){
                        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());
                        Log.d(TAG, "mode=DRAG");
                        mode = DRAG;
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        oldDist = spacing(event);
                        Log.d(TAG, "oldDist=" + oldDist);
                        if (oldDist > 10f) {
                            savedMatrix.set(matrix);
                            midPoint(mid, event);
                            mode = ZOOM;
                            Log.d(TAG, "mode=ZOOM");
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        int xDiff = (int) Math.abs(event.getX() - start.x);
                        int yDiff = (int) Math.abs(event.getY() - start.y);
                        if (xDiff < 8 && yDiff < 8){
                            performClick();
                            sPinchZoomExample.displayGallery();
                        }
                    case MotionEvent.ACTION_POINTER_UP:
                        mode = NONE;
                        Log.d(TAG, "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 newDist = spacing(event);
                            Log.d(TAG, "newDist=" + newDist);
                            if (newDist > 10f) {
                                matrix.set(savedMatrix);
                                float scale = newDist / oldDist;

                                matrix.postScale(scale, scale, mid.x, mid.y);

                                //Canvas canvas = new Canvas();

//                              Bitmap bm = Bitmap.createBitmap(sCurrentImage,0, 0, sCurrentImage.getWidth()
//                                      , sCurrentImage.getHeight(), matrix, true);
                                Log.d("SCALE", "scale=" + scale + "  " + getWidth() + "  " + getHeight());
                                //bm.recycle();
                            }
                        }
                        break;
                    }

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

            });
        }


        public void setImage(Bitmap bm, int displayWidth, int displayHeight , PinchZoomExample pze) { 
            super.setImageBitmap(bm);
            sCurrentImage = bm;
            sPinchZoomExample = pze;
            //Fit to screen.
            float scale;
            if ((displayHeight / bm.getHeight()) >= (displayWidth / bm.getWidth())){
                scale =  (float)displayWidth / (float)bm.getWidth();
            } else {
                scale = (float)displayHeight / (float)bm.getHeight();
            }

            savedMatrix.set(matrix);
            matrix.set(savedMatrix);
            matrix.postScale(scale, scale, mid.x, mid.y);
            setImageMatrix(matrix);


            // Center the image
            float redundantYSpace = (float)displayHeight - (scale * (float)bm.getHeight()) ;
            float redundantXSpace = (float)displayWidth - (scale * (float)bm.getWidth());

            redundantYSpace /= (float)2;
            redundantXSpace /= (float)2;


            savedMatrix.set(matrix);
            matrix.set(savedMatrix);
            matrix.postTranslate(redundantXSpace, redundantYSpace);   //matrix.postTranslate(50, 50);
            setImageMatrix(matrix);


        }




        /** Determine the space between the first two fingers */
        private float spacing(WrapMotionEvent 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, WrapMotionEvent event) {
            // ...
            float x = event.getX(0) + event.getX(1);
            float y = event.getY(0) + event.getY(1);
            point.set(x / 2, y / 2);
        }

}

这取决于你是如何实现的。我们能看到一些代码吗? - fredley
4个回答

7
private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 5.0f;

scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));

2
降级。这将限制一个动作(缩放手势)的比例尺。使用多个动作,用户可以超出最大或最小缩放比例。 - ALiGOTec
抱歉,我不太明白。您能详细说明一下关于多个操作以及它们如何在最大或最小缩放范围之外扩展的评论吗? - Akos Cz
每次触摸事件发生时,都会计算出一个新的“缩放比例”(即“newDist / oldDist”),并将该比例应用于“矩阵”,从而得到一个总的缩放比例,即当前矩阵缩放比例乘以当前缩放比例。在下一次触摸事件中,这个过程将重复进行(可能导致总的缩放比例大于最大缩放值MAX_ZOOM)。 - ALiGOTec
好的,但是...我上面的示例仅演示了如何确保“scale”的值严格受到MIN_ZOOM和MAX_ZOOM的限制。 - Akos Cz

3

0
创建一个临时矩阵(temp),将当前矩阵保存在其中并对temp矩阵进行缩放。然后检查temp矩阵的MSCALE_X值。
如果您的temp矩阵的缩放在您的限制范围内,请对其进行后缩放,并将其保存在另一个矩阵(savedMatrixZoom)中。如果超出了您的限制,请从SavedMatrixZoom中加载当前矩阵。
    else if (mode == ZOOM) {
        float newDist = spacing(event);
        Log.d(TAG, "newDist=" + newDist);
        if (newDist > 10f) {
            matrix.set(savedMatrix);
            zoomScale = newDist / oldDist;

            Matrix temp = new Matrix();
            temp.set(matrix);
            temp.postScale(zoomScale, zoomScale, mid.x, mid.y);
            mapZoom = getValue(temp, Matrix.MSCALE_X);
            if (mapZoom < MAX_ZOOM && mapZoom > MIN_ZOOM) {
                matrix.postScale(zoomScale, zoomScale, mid.x, mid.y);
                savedMatrixZoom.set(matrix);
            } else {
                matrix.set(savedMatrixZoom);
            }
        }
    }

希望能有所帮助


1
请解释一下 getValue(temp, Matrix.MSCALE_X) 方法。 - Vishal Patoliya ツ
1
什么是getValue? - ATES

0
if(mapZoom > MAX_ZOOM && (newDist > oldDist) ) {
    break;
} else if(mapZoom < MIN_Zoom && (newDist < oldDist) ){
    break;
}

matrix.postScale(zoomScale, zoomScale, mid.x, mid.y);  
savedMatrixZoom.set(matrix);  

它能正常工作,但仍然失去了那种流畅感,而且过于敏感。


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