Android单张图片查看、单指移动、双指缩放、双击最大化或最小化
16lz
2021-12-31
转:http://blog.csdn.net/huyiyang2010/article/details/18712997转:
Android单张图片查看、单指移动、双指缩放、双击最大化或最小化
标签:android图片移动imageviewbitmap 2014-01-23 20:05 4308人阅读 评论(6) 收藏 举报 分类: Android版权声明:本文为博主原创文章,未经博主允许不得转载。
Android平台上查看单张图片时,通常情况下需要实现图片查看、单指移动、双指缩放、双击最大化或最小化功能。
目前网络上的实现方式,都没有将此功能封装为类,零落在类和xml文件中,代码难以阅读,功能难以复用。
为此,我专门写了一个类做此功能。此类唯一的缺点是没有实现回弹动画。不说废话了,上代码。
代码如下:
- packagecom.example.test;
- importandroid.content.Context;
- importandroid.graphics.Bitmap;
- importandroid.graphics.Canvas;
- importandroid.graphics.Matrix;
- importandroid.graphics.PointF;
- importandroid.graphics.drawable.BitmapDrawable;
- importandroid.util.AttributeSet;
- importandroid.util.FloatMath;
- importandroid.util.Log;
- importandroid.view.MotionEvent;
- importandroid.widget.ImageView;
- publicclassTouchImageViewextendsImageView{
- privatePointFdown=newPointF();
- privatePointFmid=newPointF();
- <precode_snippet_id="168679"snippet_file_name="blog_20140123_1_7635608"name="code"class="java"><precode_snippet_id="168679"snippet_file_name="blog_20140123_1_7635608"name="code"class="java">privatefloatoldDist=1f;
- privateMatrixmatrix=newMatrix();
- privateMatrixpreMatrix=newMatrix();
- privateMatrixsavedMatrix=newMatrix();
- privatestaticfinalintNONE=0;
- privatestaticfinalintDRAG=1;
- privatestaticfinalintZOOM=2;
- privateintmode=NONE;
- privatebooleanisBig=false;
- privateintwidthScreen;
- privateintheightScreen;
- privateinttouchImgWidth;
- privateinttouchImgHeight;
- privatefloatdefaultScale;
- privatelonglastClickTime=0;
- privateBitmaptouchImg=null;
- privatestaticfinalintDOUBLE_CLICK_TIME_SPACE=300;
- privatestaticfinalintDOUBLE_POINT_DISTANCE=10;
- privatestaticfloatMAX_SCALE=3.0f;
- publicTouchImageView(Contextcontext){
- super(context);
- }
- publicTouchImageView(Contextcontext,AttributeSetattrs){
- super(context,attrs);
- }
- publicTouchImageView(Contextcontext,AttributeSetattrs,intdefStyleAttr){
- super(context,attrs,defStyleAttr);
- }
- publicvoidinitImageView(intscreenWidth,intscreenHeight){
- widthScreen=screenWidth;
- heightScreen=screenHeight;
- touchImg=((BitmapDrawable)getDrawable()).getBitmap();
- touchImgWidth=touchImg.getWidth();
- touchImgHeight=touchImg.getHeight();
- floatscaleX=(float)widthScreen/touchImgWidth;
- floatscaleY=(float)heightScreen/touchImgHeight;
- defaultScale=scaleX<scaleY?scaleX:scaleY;
- floatsubX=(widthScreen-touchImgWidth*defaultScale)/2;
- floatsubY=(heightScreen-touchImgHeight*defaultScale)/2;
- setScaleType(ScaleType.MATRIX);
- preMatrix.reset();
- preMatrix.postScale(defaultScale,defaultScale);
- preMatrix.postTranslate(subX,subY);
- matrix.set(preMatrix);
- invalidate();
- }
- @Override
- protectedvoidonDraw(Canvascanvas){
- if(null!=touchImg){
- canvas.save();
- canvas.drawBitmap(touchImg,matrix,null);
- canvas.restore();
- }
- }
- @Override
- publicbooleanonTouchEvent(MotionEventevent){
- switch(event.getAction()&MotionEvent.ACTION_MASK){
- caseMotionEvent.ACTION_DOWN:
- mode=DRAG;
- down.x=event.getX();
- down.y=event.getY();
- savedMatrix.set(matrix);
- if(event.getEventTime()-lastClickTime<DOUBLE_CLICK_TIME_SPACE){
- changeSize(event.getX(),event.getY());
- }
- lastClickTime=event.getEventTime();
- break;
- caseMotionEvent.ACTION_POINTER_DOWN:
- oldDist=spacing(event);
- if(oldDist>DOUBLE_POINT_DISTANCE){
- mode=ZOOM;
- //oldRotation=rotation(event);
- savedMatrix.set(matrix);
- midPoint(mid,event);
- }
- break;
- caseMotionEvent.ACTION_MOVE:
- if(mode==ZOOM){
- floatnewDist=spacing(event);
- floatscale=newDist/oldDist;
- if(scale>1.01||scale<0.99){
- preMatrix.set(savedMatrix);
- preMatrix.postScale(scale,scale,mid.x,mid.y);//缩放
- if(canZoom()){
- matrix.set(preMatrix);
- invalidate();
- }
- }
- }elseif(mode==DRAG){
- if(1.0f<distance(event,down)){
- preMatrix.set(savedMatrix);
- preMatrix.postTranslate(event.getX()-down.x,0);
- if(event.getX()>down.x){
- if(canDrag(DRAG_RIGHT)){
- savedMatrix.set(preMatrix);
- }else{
- preMatrix.set(savedMatrix);
- }
- }else{
- if(canDrag(DRAG_LEFT)){
- savedMatrix.set(preMatrix);
- }else{
- preMatrix.set(savedMatrix);
- }
- }
- preMatrix.postTranslate(0,event.getY()-down.y);
- if(event.getY()>down.y){
- if(canDrag(DRAG_DOWN)){
- savedMatrix.set(preMatrix);
- }else{
- preMatrix.set(savedMatrix);
- }
- }else{
- if(canDrag(DRAG_TOP)){
- savedMatrix.set(preMatrix);
- }else{
- preMatrix.set(savedMatrix);
- }
- }
- matrix.set(preMatrix);
- invalidate();
- down.x=event.getX();
- down.y=event.getY();
- savedMatrix.set(matrix);
- }
- }
- break;
- caseMotionEvent.ACTION_UP:
- mode=NONE;
- springback();
- break;
- caseMotionEvent.ACTION_POINTER_UP:
- mode=NONE;
- break;
- }
- returntrue;
- }
- privatevoidspringback(){
- preMatrix.set(matrix);
- float[]x=newfloat[4];
- float[]y=newfloat[4];
- getFourPoint(x,y);
- if(x[1]-x[0]>widthScreen){
- if(x[0]>0){
- preMatrix.postTranslate(-x[0],0);
- matrix.set(preMatrix);
- invalidate();
- }elseif(x[1]<widthScreen){
- preMatrix.postTranslate(widthScreen-x[1],0);
- matrix.set(preMatrix);
- invalidate();
- }
- }elseif(x[1]-x[0]<widthScreen-1f){
- preMatrix.postTranslate((widthScreen-(x[1]-x[0]))/2-x[0],0);
- matrix.set(preMatrix);
- invalidate();
- }
- if(y[2]-y[0]>heightScreen){
- if(y[0]>0){
- preMatrix.postTranslate(0,-y[0]);
- matrix.set(preMatrix);
- invalidate();
- }elseif(y[2]<heightScreen){
- preMatrix.postTranslate(0,heightScreen-y[2]);
- matrix.set(preMatrix);
- invalidate();
- }
- }elseif(y[2]-y[0]<heightScreen-1f){
- preMatrix.postTranslate(0,(heightScreen-(y[2]-y[0]))/2
- -y[0]);
- matrix.set(preMatrix);
- invalidate();
- }
- }
- privatevoidgetFourPoint(float[]x,float[]y){
- float[]f=newfloat[9];
- preMatrix.getValues(f);
- //图片4个顶点的坐标
- x[0]=f[Matrix.MSCALE_X]*0+f[Matrix.MSKEW_X]*0
- +f[Matrix.MTRANS_X];
- y[0]=f[Matrix.MSKEW_Y]*0+f[Matrix.MSCALE_Y]*0
- +f[Matrix.MTRANS_Y];
- x[1]=f[Matrix.MSCALE_X]*touchImg.getWidth()+f[Matrix.MSKEW_X]*0
- +f[Matrix.MTRANS_X];
- y[1]=f[Matrix.MSKEW_Y]*touchImg.getWidth()+f[Matrix.MSCALE_Y]*0
- +f[Matrix.MTRANS_Y];
- x[2]=f[Matrix.MSCALE_X]*0+f[Matrix.MSKEW_X]
- *touchImg.getHeight()+f[Matrix.MTRANS_X];
- y[2]=f[Matrix.MSKEW_Y]*0+f[Matrix.MSCALE_Y]
- *touchImg.getHeight()+f[Matrix.MTRANS_Y];
- x[3]=f[Matrix.MSCALE_X]*touchImg.getWidth()+f[Matrix.MSKEW_X]
- *touchImg.getHeight()+f[Matrix.MTRANS_X];
- y[3]=f[Matrix.MSKEW_Y]*touchImg.getWidth()+f[Matrix.MSCALE_Y]
- *touchImg.getHeight()+f[Matrix.MTRANS_Y];
- }
- privatefinalstaticintDRAG_LEFT=0;
- privatefinalstaticintDRAG_RIGHT=1;
- privatefinalstaticintDRAG_TOP=2;
- privatefinalstaticintDRAG_DOWN=3;
- privatebooleancanDrag(finalintdirection){
- float[]x=newfloat[4];
- float[]y=newfloat[4];
- getFourPoint(x,y);
- //出界判断
- if((x[0]>0||x[2]>0||x[1]<widthScreen||x[3]<widthScreen)
- &&(y[0]>0||y[1]>0||y[2]<heightScreen||y[3]<heightScreen)){
- returnfalse;
- }
- if(DRAG_LEFT==direction){
- //左移出界判断
- if(x[1]<widthScreen||x[3]<widthScreen){
- returnfalse;
- }
- }elseif(DRAG_RIGHT==direction){
- //右移出界判断
- if(x[0]>0||x[2]>0){
- returnfalse;
- }
- }elseif(DRAG_TOP==direction){
- //上移出界判断
- if(y[2]<heightScreen||y[3]<heightScreen){
- returnfalse;
- }
- }elseif(DRAG_DOWN==direction){
- //下移出界判断
- if(y[0]>0||y[1]>0){
- returnfalse;
- }
- }else{
- returnfalse;
- }
- returntrue;
- }
- privatebooleancanZoom(){
- float[]x=newfloat[4];
- float[]y=newfloat[4];
- getFourPoint(x,y);
- //图片现宽度
- doublewidth=Math.sqrt((x[0]-x[1])*(x[0]-x[1])+(y[0]-y[1])
- *(y[0]-y[1]));
- doubleheight=Math.sqrt((x[0]-x[2])*(x[0]-x[2])+(y[0]-y[2])
- *(y[0]-y[2]));
- //缩放比率判断
- if(width<touchImgWidth*defaultScale-1
- ||width>touchImgWidth*MAX_SCALE+1){
- returnfalse;
- }
- //出界判断
- if(width<widthScreen&&height<heightScreen){
- returnfalse;
- }
- returntrue;
- }
- //触碰两点间距离
- privatestaticfloatspacing(MotionEventevent){
- floatx=event.getX(0)-event.getX(1);
- if(x<0){
- x=-x;
- }
- floaty=event.getY(0)-event.getY(1);
- if(y<0){
- y=-y;
- }
- returnFloatMath.sqrt(x*x+y*y);
- }
- //取手势中心点
- privatestaticvoidmidPoint(PointFpoint,MotionEventevent){
- floatx=event.getX(0)+event.getX(1);
- floaty=event.getY(0)+event.getY(1);
- point.set(x/2,y/2);
- }
- //取两点之间的距离
- privatestaticfloatdistance(MotionEventpoint2,PointFpoint1){
- floatx=point1.x-point2.getX();
- if(x<0){
- x=-x;
- }
- floaty=point1.y-point2.getY();
- if(y<0){
- y=-y;
- }
- returnFloatMath.sqrt(x*x+y*y);
- }
- privatevoidchangeSize(floatx,floaty){
- if(isBig){
- floatsubX=(widthScreen-touchImgWidth*defaultScale)/2;
- floatsubY=(heightScreen-touchImgHeight*defaultScale)/2;
- preMatrix.reset();
- preMatrix.postScale(defaultScale,defaultScale);
- preMatrix.postTranslate(subX,subY);
- matrix.set(preMatrix);
- invalidate();
- isBig=false;
- }else{
- floattransX=(widthScreen-touchImgWidth*MAX_SCALE)/2;
- floattransY=(heightScreen-touchImgHeight*MAX_SCALE)/2;
- preMatrix.reset();
- preMatrix.postScale(MAX_SCALE,MAX_SCALE);
- preMatrix.postTranslate(transX,transY);
- matrix.set(preMatrix);
- invalidate();
- isBig=true;
- }
- }
- }
- </pre>
- <pre></pre>
- <pre></pre>
- <p></p>
- <pre></pre>
- <pre></pre>
- <p><br>
- </p>
- <p><br>
- </p>
- <p></p>
- <p>测试代码如下:</p>
- <p><br>
- </p>
- <p>activity_main.xml文件:</p>
- <p></p>
- <precode_snippet_id="168679"snippet_file_name="blog_20140123_2_8257273"name="code"class="html"><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/layout_id"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".MainActivity">
- <com.example.test.TouchImageView
- android:id="@+id/img_id"
- android:layout_width="400dip"
- android:layout_height="800dip"
- android:src="@drawable/banner"
- android:scaleType="fitCenter"/>
- </LinearLayout>
- </pre><br>
- <p><br>
- </p>
- <p>MainActivity.java文件:</p>
- <p></p>
- <p></p>
- <precode_snippet_id="168679"snippet_file_name="blog_20140123_3_2367928"name="code"class="java">packagecom.example.test;
- importandroid.app.Activity;
- importandroid.os.Bundle;
- importandroid.util.DisplayMetrics;
- importandroid.view.Menu;
- importandroid.view.ViewTreeObserver.OnGlobalLayoutListener;
- importandroid.widget.LinearLayout;
- publicclassMainActivityextendsActivity{
- privateTouchImageViewimgView;
- @Override
- protectedvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- DisplayMetricsdm=newDisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(dm);
- TouchImageViewimgView=(TouchImageView)findViewById(R.id.img_id);
- imgView.initImageView(dm.widthPixels,dm.heightPixels-80);
- }
- @Override
- publicbooleanonCreateOptionsMenu(Menumenu){
- //Inflatethemenu;thisaddsitemstotheactionbarifitispresent.
- getMenuInflater().inflate(R.menu.main,menu);
- returntrue;
- }
- }
- </pre><br>
- <br>
- <p></p>
- </pre>
更多相关文章
- android – 多屏幕适配相关
- Android(安卓)调用微信登陆、支付、分享,出现的白屏、黑屏、闪屏
- Android高手进阶教程(十一)--Android(安卓)通用获取Ip的方法(判
- Android(安卓)判断应用程序安装位置
- Android(安卓)实现图片的自动缩放,适应分辨率不同的手机
- Android中实现双指缩放的功能
- android判断文件类型是否为音频文件
- Android(安卓)上传头像(文件)到服务器
- Android和J2ME按钮接口之简单对比