对于图片的移动、缩放的操作,以前处理过好几次,但是都没有过总结。最近在修复以前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);
}