安卓實現圖片移動縮放,限定邊界

對於圖片的移動、縮放的操作,以前處理過好幾次,但是都沒有過總結。最近在修復以前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);
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章