java - 使用自定义 imageView 缩小配置图像

标签 java android eclipse swing

我正在使用以下代码在 ViewPager 中添加自定义 ImagView 以设置缩放系统。双击,你放大,然后再次双击你缩小。现在假设你轻扫并放大一点,现在我想要一个功能,如果你现在双击它应该缩小你。

如果我调用函数 minZoomed(),它会缩小但现在不会居中。但是,如果我首先完全放大然后双击缩小,它确实会使图像居中。但是当我使用滑动放大一点然后尝试缩小时,它会将图像移动到一些随机位置。我希望图像在缩小后在屏幕上居中

所以

首先完全缩小(居中)>双击>完全放大(居中)>双击>完全缩小(居中)

但是

首先完全缩小(居中)>滑动缩放>小缩放(居中)>双击>完全缩小(移位) 我该如何解决这个问题?

public class ZoomImageView extends ImageView
{
    Matrix matrix = new Matrix();

    static final int NONE = 0;
    static final int DRAG = 1;
    static final int ZOOM = 2;
    int mode = NONE;

    boolean isMaxed = false;
    boolean zoomOut = false;

    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 mDoubleDetector;
    Context context;

    private CustomViewPager pager;

    public ZoomImageView(Context context) 
    {
        super(context);
        super.setClickable(true);
        this.context = context;
        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
        mDoubleDetector = new GestureDetector(context, new DoubleTapGestureDetector());
        matrix.setTranslate(1f, 1f);
        m = new float[9];
        setImageMatrix(matrix);
        setScaleType(ScaleType.MATRIX);

        setOnTouchListener(new OnTouchListener() 
        {
            public boolean onTouch(View v, MotionEvent event) 
            {
                mScaleDetector.onTouchEvent(event);
                mDoubleDetector.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);
                if (saveScale == minScale)
                {
                    pager.setPagingEnabled(true);
                }
                else 
                {
                    pager.setPagingEnabled(false);
                }
                return true; 
            }

        });
    }

    public void setPager(CustomViewPager pager)
    {
        this.pager = pager;
    }

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

    public void minZoomed()
    {
        matrix.setScale(minScale,minScale);
        setImageMatrix(matrix);
        invalidate();
        redundantYSpace = (float)height - (minScale * (float)bmHeight) ;
        redundantXSpace = (float)width - (minScale * (float)bmWidth);
        redundantYSpace /= (float)2;
        redundantXSpace /= (float)2;
        saveScale = minScale;
        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);
        invalidate();
    }

    public void maxZoomed()
    {
        matrix.setScale(maxScale,maxScale);
        setImageMatrix(matrix);
        redundantYSpace = (float)height - (maxScale * (float)bmHeight) ;
        redundantXSpace = (float)width - (maxScale * (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);
        invalidate();
        saveScale = maxScale;

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

    public void setMinZoom(float x)
    {
        minScale = 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 = (float)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05);
            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;
        }
    }

    @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 =  (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);   
    }

    private class DoubleTapGestureDetector extends GestureDetector.SimpleOnGestureListener 
    {
        @Override
        public boolean onDown(MotionEvent e) 
        {
            return true;
        }

        @Override
        public boolean onDoubleTap(MotionEvent e) 
        {

            if( isMaxed == false)
            {
                isMaxed = true;
                maxZoomed();
                pager.setPagingEnabled(false);
            }
            else
            {
                isMaxed = false;
                minZoomed();
                pager.setPagingEnabled(true);
            }


            return true;
        }
    }

}

最佳答案

你可以看看这个项目:https://github.com/sephiroth74/ImageViewZoom

它支持双指缩放和双击,而且非常容易实现(我自己用过)

所有功劳归于sephiroth74

关于java - 使用自定义 imageView 缩小配置图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14073594/

相关文章:

Java int 到 python int

android - 从 Android 中的文件加载 SSL 证书

android - 使用 Firebase 检测 RecyclerView 项目中的删除

android - 让拆分的 ActionBar 显示两倍的图标

java - Eclipse:模式无法解析为类型

java - 将 zip 文件从服务器下载到设备时出错?

java - hibernate 中的异常 "org.hibernate.PersistentObjectException"

java - eclipse junit 差异窗口

java - 如何将 WebLogic Server 配置到现有 Eclipse

java - 将 Spring 项目上传到有/没有服务器的 github 帐户以及如何嵌入 mysql 数据库