Android多点触控技术实战自由地对图片进行缩放和移动.docx
- 文档编号:4310911
- 上传时间:2022-11-29
- 格式:DOCX
- 页数:18
- 大小:75.98KB
Android多点触控技术实战自由地对图片进行缩放和移动.docx
《Android多点触控技术实战自由地对图片进行缩放和移动.docx》由会员分享,可在线阅读,更多相关《Android多点触控技术实战自由地对图片进行缩放和移动.docx(18页珍藏版)》请在冰豆网上搜索。
Android多点触控技术实战自由地对图片进行缩放和移动
Android多点触控技术实战,自由地对图片进行缩放和移动
在Android瀑布流照片墙的效果这篇文章中,虽然这种效果很炫很酷,但其实还只能算是一个半成品,因为照片墙中所有的图片都是只能看不能点的。
因此本篇文章中,我们就来对这一功能进行完善,加入点击图片就能浏览大图的功能,并且在浏览大图的时候还可以通过多点触控的方式对图片进行缩放。
我们现在就开始动手吧,首先打开上次的PhotoWallFallsDemo项目,在里面加入一个ZoomImageView类,这个类就是用于进行大图展示和多点触控缩放的,代码如下所示:
[java]viewplaincopy
publicclassZoomImageViewextendsView{
/**
*初始化状态常量
*/
publicstaticfinalintSTATUS_INIT=1;
/**
*图片放大状态常量
*/
publicstaticfinalintSTATUS_ZOOM_OUT=2;
/**
*图片缩小状态常量
*/
publicstaticfinalintSTATUS_ZOOM_IN=3;
/**
*图片拖动状态常量
*/
publicstaticfinalintSTATUS_MOVE=4;
/**
*用于对图片进行移动和缩放变换的矩阵
*/
privateMatrixmatrix=newMatrix();
/**
*待展示的Bitmap对象
*/
privateBitmapsourceBitmap;
/**
*记录当前操作的状态,可选值为STATUS_INIT、STATUS_ZOOM_OUT、STATUS_ZOOM_IN和STATUS_MOVE
*/
privateintcurrentStatus;
/**
*ZoomImageView控件的宽度
*/
privateintwidth;
/**
*ZoomImageView控件的高度
*/
privateintheight;
/**
*记录两指同时放在屏幕上时,中心点的横坐标值
*/
privatefloatcenterPointX;
/**
*记录两指同时放在屏幕上时,中心点的纵坐标值
*/
privatefloatcenterPointY;
/**
*记录当前图片的宽度,图片被缩放时,这个值会一起变动
*/
privatefloatcurrentBitmapWidth;
/**
*记录当前图片的高度,图片被缩放时,这个值会一起变动
*/
privatefloatcurrentBitmapHeight;
/**
*记录上次手指移动时的横坐标
*/
privatefloatlastXMove=-1;
/**
*记录上次手指移动时的纵坐标
*/
privatefloatlastYMove=-1;
/**
*记录手指在横坐标方向上的移动距离
*/
privatefloatmovedDistanceX;
/**
*记录手指在纵坐标方向上的移动距离
*/
privatefloatmovedDistanceY;
/**
*记录图片在矩阵上的横向偏移值
*/
privatefloattotalTranslateX;
/**
*记录图片在矩阵上的纵向偏移值
*/
privatefloattotalTranslateY;
/**
*记录图片在矩阵上的总缩放比例
*/
privatefloattotalRatio;
/**
*记录手指移动的距离所造成的缩放比例
*/
privatefloatscaledRatio;
/**
*记录图片初始化时的缩放比例
*/
privatefloatinitRatio;
/**
*记录上次两指之间的距离
*/
privatedoublelastFingerDis;
/**
*ZoomImageView构造函数,将当前操作状态设为STATUS_INIT。
*
*@paramcontext
*@paramattrs
*/
publicZoomImageView(Contextcontext,AttributeSetattrs){
super(context,attrs);
currentStatus=STATUS_INIT;
}
/**
*将待展示的图片设置进来。
*
*@parambitmap
*待展示的Bitmap对象
*/
publicvoidsetImageBitmap(Bitmapbitmap){
sourceBitmap=bitmap;
invalidate();
}
@Override
protectedvoidonLayout(booleanchanged,intleft,inttop,intright,intbottom){
super.onLayout(changed,left,top,right,bottom);
if(changed){
//分别获取到ZoomImageView的宽度和高度
width=getWidth();
height=getHeight();
}
}
@Override
publicbooleanonTouchEvent(MotionEventevent){
switch(event.getActionMasked()){
caseMotionEvent.ACTION_POINTER_DOWN:
if(event.getPointerCount()==2){
//当有两个手指按在屏幕上时,计算两指之间的距离
lastFingerDis=distanceBetweenFingers(event);
}
break;
caseMotionEvent.ACTION_MOVE:
if(event.getPointerCount()==1){
//只有单指按在屏幕上移动时,为拖动状态
floatxMove=event.getX();
floatyMove=event.getY();
if(lastXMove==-1&&lastYMove==-1){
lastXMove=xMove;
lastYMove=yMove;
}
currentStatus=STATUS_MOVE;
movedDistanceX=xMove-lastXMove;
movedDistanceY=yMove-lastYMove;
//进行边界检查,不允许将图片拖出边界
if(totalTranslateX+movedDistanceX>0){
movedDistanceX=0;
}elseif(width-(totalTranslateX+movedDistanceX)>currentBitmapWidth){
movedDistanceX=0;
}
if(totalTranslateY+movedDistanceY>0){
movedDistanceY=0;
}elseif(height-(totalTranslateY+movedDistanceY)>currentBitmapHeight){
movedDistanceY=0;
}
//调用onDraw()方法绘制图片
invalidate();
lastXMove=xMove;
lastYMove=yMove;
}elseif(event.getPointerCount()==2){
//有两个手指按在屏幕上移动时,为缩放状态
centerPointBetweenFingers(event);
doublefingerDis=distanceBetweenFingers(event);
if(fingerDis>lastFingerDis){
currentStatus=STATUS_ZOOM_OUT;
}else{
currentStatus=STATUS_ZOOM_IN;
}
//进行缩放倍数检查,最大只允许将图片放大4倍,最小可以缩小到初始化比例
if((currentStatus==STATUS_ZOOM_OUT&&totalRatio<4*initRatio)
||(currentStatus==STATUS_ZOOM_IN&&totalRatio>initRatio)){
scaledRatio=(float)(fingerDis/lastFingerDis);
totalRatio=totalRatio*scaledRatio;
if(totalRatio>4*initRatio){
totalRatio=4*initRatio;
}elseif(totalRatio totalRatio=initRatio; } //调用onDraw()方法绘制图片 invalidate(); lastFingerDis=fingerDis; } } break; caseMotionEvent.ACTION_POINTER_UP: if(event.getPointerCount()==2){ //手指离开屏幕时将临时值还原 lastXMove=-1; lastYMove=-1; } break; caseMotionEvent.ACTION_UP: //手指离开屏幕时将临时值还原 lastXMove=-1; lastYMove=-1; break; default: break; } returntrue; } /** *根据currentStatus的值来决定对图片进行什么样的绘制操作。 */ @Override protectedvoidonDraw(Canvascanvas){ super.onDraw(canvas); switch(currentStatus){ caseSTATUS_ZOOM_OUT: caseSTATUS_ZOOM_IN: zoom(canvas); break; caseSTATUS_MOVE: move(canvas); break; caseSTATUS_INIT: initBitmap(canvas); default: canvas.drawBitmap(sourceBitmap,matrix,null); break; } } /** *对图片进行缩放处理。 * *@paramcanvas */ privatevoidzoom(Canvascanvas){ matrix.reset(); //将图片按总缩放比例进行缩放 matrix.postScale(totalRatio,totalRatio); floatscaledWidth=sourceBitmap.getWidth()*totalRatio; floatscaledHeight=sourceBitmap.getHeight()*totalRatio; floattranslateX=0f; floattranslateY=0f; //如果当前图片宽度小于屏幕宽度,则按屏幕中心的横坐标进行水平缩放。 否则按两指的中心点的横坐标进行水平缩放 if(currentBitmapWidth translateX=(width-scaledWidth)/2f; }else{ translateX=totalTranslateX*scaledRatio+centerPointX*(1-scaledRatio); //进行边界检查,保证图片缩放后在水平方向上不会偏移出屏幕 if(translateX>0){ translateX=0; }elseif(width-translateX>scaledWidth){ translateX=width-scaledWidth; } } //如果当前图片高度小于屏幕高度,则按屏幕中心的纵坐标进行垂直缩放。 否则按两指的中心点的纵坐标进行垂直缩放 if(currentBitmapHeight translateY=(height-scaledHeight)/2f; }else{ translateY=totalTranslateY*scaledRatio+centerPointY*(1-scaledRatio); //进行边界检查,保证图片缩放后在垂直方向上不会偏移出屏幕 if(translateY>0){ translateY=0; }elseif(height-translateY>scaledHeight){ translateY=height-scaledHeight; } } //缩放后对图片进行偏移,以保证缩放后中心点位置不变 matrix.postTranslate(translateX,translateY); totalTranslateX=translateX; totalTranslateY=translateY; currentBitmapWidth=scaledWidth; currentBitmapHeight=scaledHeight; canvas.drawBitmap(sourceBitmap,matrix,null); } /** *对图片进行平移处理 * *@paramcanvas */ privatevoidmove(Canvascanvas){ matrix.reset(); //根据手指移动的距离计算出总偏移值 floattranslateX=totalTranslateX+movedDistanceX; floattranslateY=totalTranslateY+movedDistanceY; //先按照已有的缩放比例对图片进行缩放 matrix.postScale(totalRatio,totalRatio); //再根据移动距离进行偏移 matrix.postTranslate(translateX,translateY); totalTranslateX=translateX; totalTranslateY=translateY; canvas.drawBitmap(sourceBitmap,matrix,null); } /** *对图片进行初始化操作,包括让图片居中,以及当图片大于屏幕宽高时对图片进行压缩。 * *@paramcanvas */ privatevoidinitBitmap(Canvascanvas){ if(sourceBitmap! =null){ set(); intbitmapWidth=sourceBitmap.getWidth(); intbitmapHeight=sourceBitmap.getHeight(); if(bitmapWidth>width||bitmapHeight>height){ if(bitmapWidth-width>bitmapHeight-height){ //当图片宽度大于屏幕宽度时,将图片等比例压缩,使它可以完全显示出来 floatratio=width/(bitmapWidth*1.0f); matrix.postScale(ratio,ratio); floattranslateY=(height-(bitmapHeight*ratio))/2f; //在纵坐标方向上进行偏移,以保证图片居中显示 matrix.postTranslate(0,translateY); totalTranslateY=translateY; totalRatio=initRatio=ratio; }else{ //当图片高度大于屏幕高度时,将图片等比例压缩,使它可以完全显示出来 floatratio=height/(bitmapHeight*1.0f); matrix.postScale(ratio,ratio); floattranslateX=(width-(bitmapWidth*ratio))/2f; //在横坐标方向上进行偏移,以保证图片居中显示 matrix.postTranslate(translateX,0); totalTranslateX=translateX; totalRatio=initRatio=ratio; } currentBitmapWidth=bitmapWidth*initRatio; currentBitmapHeight=bitmapHeight*initRatio; }else{ //当图片的宽高都小于屏幕宽高时,直接让图片居中显示 floattranslateX=(width-sourceBitmap.getWidth())/2f; floattranslateY=(height-sourceBitmap.getHeight())/2f; matrix.postTranslate(translateX,translateY); totalTranslateX=translateX; totalTranslateY=translateY; totalRatio=initRatio=1f; currentBitmapWidth=bitmapWidth; currentBitmapHeight=bitmapHeight; } canvas.drawBitmap(sourceBitmap,matrix,null); } } /** *计算两个手指之间的距离。 * *@paramevent *@return两个手指之间的距离 */ privatedoubledistanceBetweenFingers(MotionEventevent){ floatdisX=Math.abs(event.getX(0)-event.getX (1)); floatdisY=Math.abs(event.getY(0)-event.getY (1)); returnMath.sqrt(disX*disX+disY*disY); } /** *计算两个手指之间中心点的坐标。 * *@paramevent */ privatevoidcenterPointBetweenFingers(MotionEventevent){ floatxPoint0=event.getX(0); floatyPoint0=event.getY(0); floatxPoint1=event.getX (1); floatyPoint1=event.getY (1); centerPointX=(xPoint0+xPoint1)/2; centerPointY=(yPoint0+yPoint1)/2; } } 由于这个类是整个多点触控缩放功能最核心的一个类,我在这里给大家详细的讲解一下。 首先在ZoomImageView里我们定义了四种状态,STATUS_INIT、STATUS_ZOOM_OUT、STATUS_ZOOM_IN和STATUS_MOVE,这四个状态分别代表初始化、放大、缩小和移动这几个动作,然后在构造函数里我们将当前状态置为初始化状态。 接着我们可以调用setImageBitmap()方法把要显示的图片对象传进去,这个方法会invalidate一下当前的View,因此onDraw()方法就会得到执行。 然后在onDraw()方法里判断出当前的状态是初始化状态,所以就会调用initBitmap()方法进行初始化操作。 那我们就来看一下initBitmap()方法,在这个方法中首先对图片的大小进行了判断,如果图片的宽和高都是小于屏幕的宽和高的,则直接将这张图片进行偏移,让它能够居中显示在屏幕上。 如果图片的宽度大于屏幕的宽度,或者图片的高度大于屏幕的
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Android 多点 技术 实战 自由 图片 进行 缩放 移动