對於圖片的移動、縮放的操作,以前處理過好幾次,但是都沒有過總結。最近在修復以前bug的時候,給圖片的移動、縮放添加了邊界,感覺寫的還可以,思路也比較清晰,特此記錄一下。希望能幫到有需要的人,有錯誤的地方也請大家能指出。
實現的功能
如經常使用的圖片查看器
1、可以移動、縮放
2、移動和縮放過程中圖片不超過屏幕邊界
3、支持最大、最小縮放尺寸
關於第1、3點實現起來很簡單,這裏不過多闡述。文章主要講如何限定邊界
實現的效果
哈哈,圖片是我最近烙的餅
實現原理
移動時限定邊界:通過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;
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);
}