安卓实现图片移动缩放,限定边界

对于图片的移动、缩放的操作,以前处理过好几次,但是都没有过总结。最近在修复以前bug的时候,给图片的移动、缩放添加了边界,感觉写的还可以,思路也比较清晰,特此记录一下。希望能帮到有需要的人,有错误的地方也请大家能指出。

实现的功能

如经常使用的图片查看器

1、可以移动、缩放

2、移动和缩放过程中图片不超过屏幕边界

3、支持最大、最小缩放尺寸

关于第1、3点实现起来很简单,这里不过多阐述。文章主要讲如何限定边界

实现的效果

zoom.gif

哈哈,图片是我最近烙的饼

实现原理

移动时限定边界:通过matrix.mapRect来获取当前图片的Rect信息,来限定移动

缩放时限定边界:先进行缩放,通过上面的限定移动来移动到合适的位置

具体实现

当前图片的Recct信息

RectF tmpRect =new RectF();

matrix.mapRect(tmpRect,new RectF(0,0,imageBitmap.getWidth(),imageBitmap.getHeight()))

如果返回true表示获取成功

移动时限定边界

我们先考虑x轴方向,当手指向左滑动时图片向左移动,dx为负值,那么图片可以移动的最大距离为下图中的minDx(因为是负数,这里命名为minDx);表达式为minDx = this.getWidth() - (tmpRect.left+tmpRect.width());

当手指向右滑动时图片向右移动,dx为正值,那么图片可以移动的最大距离为下图中的maxDx(也是是dx的最大值);表达式为minDx = -tmpRect.left;
新建位图图像.png

y方向的计算同理。

代码具体实现如下

private void imageMove(float toDx,float toDy,boolean pre){
        if (pre){
            matrix.set(savedMatrix);
        }
        RectF tmpRect = new RectF();
        if (matrix.mapRect(tmpRect,
                new RectF(0, 0, imageBitmap.getWidth(),
                        imageBitmap.getHeight()))){
            if (tmpRect.width()<=this.getWidth()){
                toDx = (this.getWidth() - tmpRect.width())/2 - tmpRect.left;
            }else {
                float minDx = this.getWidth() - (tmpRect.left+tmpRect.width());
                float maxDx = -tmpRect.left;
                if (toDx<0){
                    toDx = Math.max(minDx,toDx);
                }else if (toDx>0){
                    toDx = Math.min(maxDx,toDx);
                }else {
                    if (minDx>0){
                        toDx = minDx;
                    }else if (maxDx<0){
                        toDx = maxDx;
                    }
                }
            }
            if (tmpRect.height()<=this.getHeight()){
                 toDy = (this.getHeight() - tmpRect.height())/2 -tmpRect.top;
            }else {
                float minDy = this.getHeight() - (tmpRect.top+tmpRect.height());
                float maxDy = -tmpRect.top;
                if (toDy<0){
                    toDy = Math.max(minDy,toDy);
                }else if (toDy>0){
                    toDy = Math.min(maxDy,toDy);
                }else {
                    if (minDy>0){
                        toDy = minDy;
                    }else if (maxDy<0){
                        toDy = maxDy;
                    }
                }
            }
            if (toDx == 0 && toDy ==0){
                return;
            }
            matrix.postTranslate(toDx,
                    toDy);
        }
    }

缩放时限定边界

主要通过matrix的preScale和postTranslate来实现,代码如下

private void imageZoom(float toScale){
        matrix.set(savedMatrix);
        RectF tmpRect = new RectF();
        if (!matrix.mapRect(tmpRect,
                new RectF(0, 0, imageBitmap.getWidth(),
                        imageBitmap.getHeight()))){
            return;
        }

        if (toScale>=1){
            float maxWidth = this.getWidth()*10;
            float maxHeight = this.getHeight()*10;
            if (tmpRect.width()*toScale >maxWidth){
                toScale = maxWidth/tmpRect.width();
            }
            if (tmpRect.height()*toScale > maxHeight){
                toScale = Math.min(toScale,maxHeight/tmpRect.height());
            }
            if (toScale == 1){
                return;
            }
        }else if (toScale >= 0.2) {
            float minWidth = Math.min(600,imageBitmap.getWidth());
            float minHeight = Math.min(600,imageBitmap.getHeight());
            if (tmpRect.width()*toScale <minWidth && tmpRect.height()*toScale < minHeight){
                toScale = Math.min(minWidth/tmpRect.width(),minHeight/tmpRect.height());
            }
            if (toScale == 1){
                return;
            }
        }

        matrix.preScale(toScale, toScale,
                middlePoint.x, middlePoint.y);
        imageMove(0,0,false);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章