转:http://blog.csdn.net/huyiyang2010/article/details/18712997转:

Android单张图片查看、单指移动、双指缩放、双击最大化或最小化

标签:android图片移动imageviewbitmap 4308人阅读 评论(6) 收藏 举报 分类: Android

Android平台上查看单张图片时,通常情况下需要实现图片查看、单指移动、双指缩放、双击最大化或最小化功能。

目前网络上的实现方式,都没有将此功能封装为类,零落在类和xml文件中,代码难以阅读,功能难以复用。

为此,我专门写了一个类做此功能。此类唯一的缺点是没有实现回弹动画。不说废话了,上代码。

代码如下:

[java] view plain copy
  1. packagecom.example.test;
  2. importandroid.content.Context;
  3. importandroid.graphics.Bitmap;
  4. importandroid.graphics.Canvas;
  5. importandroid.graphics.Matrix;
  6. importandroid.graphics.PointF;
  7. importandroid.graphics.drawable.BitmapDrawable;
  8. importandroid.util.AttributeSet;
  9. importandroid.util.FloatMath;
  10. importandroid.util.Log;
  11. importandroid.view.MotionEvent;
  12. importandroid.widget.ImageView;
  13. publicclassTouchImageViewextendsImageView{
  14. privatePointFdown=newPointF();
  15. privatePointFmid=newPointF();
  16. <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;
  17. privateMatrixmatrix=newMatrix();
  18. privateMatrixpreMatrix=newMatrix();
  19. privateMatrixsavedMatrix=newMatrix();
  20. privatestaticfinalintNONE=0;
  21. privatestaticfinalintDRAG=1;
  22. privatestaticfinalintZOOM=2;
  23. privateintmode=NONE;
  24. privatebooleanisBig=false;
  25. privateintwidthScreen;
  26. privateintheightScreen;
  27. privateinttouchImgWidth;
  28. privateinttouchImgHeight;
  29. privatefloatdefaultScale;
  30. privatelonglastClickTime=0;
  31. privateBitmaptouchImg=null;
  32. privatestaticfinalintDOUBLE_CLICK_TIME_SPACE=300;
  33. privatestaticfinalintDOUBLE_POINT_DISTANCE=10;
  34. privatestaticfloatMAX_SCALE=3.0f;
  35. publicTouchImageView(Contextcontext){
  36. super(context);
  37. }
  38. publicTouchImageView(Contextcontext,AttributeSetattrs){
  39. super(context,attrs);
  40. }
  41. publicTouchImageView(Contextcontext,AttributeSetattrs,intdefStyleAttr){
  42. super(context,attrs,defStyleAttr);
  43. }
  44. publicvoidinitImageView(intscreenWidth,intscreenHeight){
  45. widthScreen=screenWidth;
  46. heightScreen=screenHeight;
  47. touchImg=((BitmapDrawable)getDrawable()).getBitmap();
  48. touchImgWidth=touchImg.getWidth();
  49. touchImgHeight=touchImg.getHeight();
  50. floatscaleX=(float)widthScreen/touchImgWidth;
  51. floatscaleY=(float)heightScreen/touchImgHeight;
  52. defaultScale=scaleX<scaleY?scaleX:scaleY;
  53. floatsubX=(widthScreen-touchImgWidth*defaultScale)/2;
  54. floatsubY=(heightScreen-touchImgHeight*defaultScale)/2;
  55. setScaleType(ScaleType.MATRIX);
  56. preMatrix.reset();
  57. preMatrix.postScale(defaultScale,defaultScale);
  58. preMatrix.postTranslate(subX,subY);
  59. matrix.set(preMatrix);
  60. invalidate();
  61. }
  62. @Override
  63. protectedvoidonDraw(Canvascanvas){
  64. if(null!=touchImg){
  65. canvas.save();
  66. canvas.drawBitmap(touchImg,matrix,null);
  67. canvas.restore();
  68. }
  69. }
  70. @Override
  71. publicbooleanonTouchEvent(MotionEventevent){
  72. switch(event.getAction()&MotionEvent.ACTION_MASK){
  73. caseMotionEvent.ACTION_DOWN:
  74. mode=DRAG;
  75. down.x=event.getX();
  76. down.y=event.getY();
  77. savedMatrix.set(matrix);
  78. if(event.getEventTime()-lastClickTime<DOUBLE_CLICK_TIME_SPACE){
  79. changeSize(event.getX(),event.getY());
  80. }
  81. lastClickTime=event.getEventTime();
  82. break;
  83. caseMotionEvent.ACTION_POINTER_DOWN:
  84. oldDist=spacing(event);
  85. if(oldDist>DOUBLE_POINT_DISTANCE){
  86. mode=ZOOM;
  87. //oldRotation=rotation(event);
  88. savedMatrix.set(matrix);
  89. midPoint(mid,event);
  90. }
  91. break;
  92. caseMotionEvent.ACTION_MOVE:
  93. if(mode==ZOOM){
  94. floatnewDist=spacing(event);
  95. floatscale=newDist/oldDist;
  96. if(scale>1.01||scale<0.99){
  97. preMatrix.set(savedMatrix);
  98. preMatrix.postScale(scale,scale,mid.x,mid.y);//缩放
  99. if(canZoom()){
  100. matrix.set(preMatrix);
  101. invalidate();
  102. }
  103. }
  104. }elseif(mode==DRAG){
  105. if(1.0f<distance(event,down)){
  106. preMatrix.set(savedMatrix);
  107. preMatrix.postTranslate(event.getX()-down.x,0);
  108. if(event.getX()>down.x){
  109. if(canDrag(DRAG_RIGHT)){
  110. savedMatrix.set(preMatrix);
  111. }else{
  112. preMatrix.set(savedMatrix);
  113. }
  114. }else{
  115. if(canDrag(DRAG_LEFT)){
  116. savedMatrix.set(preMatrix);
  117. }else{
  118. preMatrix.set(savedMatrix);
  119. }
  120. }
  121. preMatrix.postTranslate(0,event.getY()-down.y);
  122. if(event.getY()>down.y){
  123. if(canDrag(DRAG_DOWN)){
  124. savedMatrix.set(preMatrix);
  125. }else{
  126. preMatrix.set(savedMatrix);
  127. }
  128. }else{
  129. if(canDrag(DRAG_TOP)){
  130. savedMatrix.set(preMatrix);
  131. }else{
  132. preMatrix.set(savedMatrix);
  133. }
  134. }
  135. matrix.set(preMatrix);
  136. invalidate();
  137. down.x=event.getX();
  138. down.y=event.getY();
  139. savedMatrix.set(matrix);
  140. }
  141. }
  142. break;
  143. caseMotionEvent.ACTION_UP:
  144. mode=NONE;
  145. springback();
  146. break;
  147. caseMotionEvent.ACTION_POINTER_UP:
  148. mode=NONE;
  149. break;
  150. }
  151. returntrue;
  152. }
  153. privatevoidspringback(){
  154. preMatrix.set(matrix);
  155. float[]x=newfloat[4];
  156. float[]y=newfloat[4];
  157. getFourPoint(x,y);
  158. if(x[1]-x[0]>widthScreen){
  159. if(x[0]>0){
  160. preMatrix.postTranslate(-x[0],0);
  161. matrix.set(preMatrix);
  162. invalidate();
  163. }elseif(x[1]<widthScreen){
  164. preMatrix.postTranslate(widthScreen-x[1],0);
  165. matrix.set(preMatrix);
  166. invalidate();
  167. }
  168. }elseif(x[1]-x[0]<widthScreen-1f){
  169. preMatrix.postTranslate((widthScreen-(x[1]-x[0]))/2-x[0],0);
  170. matrix.set(preMatrix);
  171. invalidate();
  172. }
  173. if(y[2]-y[0]>heightScreen){
  174. if(y[0]>0){
  175. preMatrix.postTranslate(0,-y[0]);
  176. matrix.set(preMatrix);
  177. invalidate();
  178. }elseif(y[2]<heightScreen){
  179. preMatrix.postTranslate(0,heightScreen-y[2]);
  180. matrix.set(preMatrix);
  181. invalidate();
  182. }
  183. }elseif(y[2]-y[0]<heightScreen-1f){
  184. preMatrix.postTranslate(0,(heightScreen-(y[2]-y[0]))/2
  185. -y[0]);
  186. matrix.set(preMatrix);
  187. invalidate();
  188. }
  189. }
  190. privatevoidgetFourPoint(float[]x,float[]y){
  191. float[]f=newfloat[9];
  192. preMatrix.getValues(f);
  193. //图片4个顶点的坐标
  194. x[0]=f[Matrix.MSCALE_X]*0+f[Matrix.MSKEW_X]*0
  195. +f[Matrix.MTRANS_X];
  196. y[0]=f[Matrix.MSKEW_Y]*0+f[Matrix.MSCALE_Y]*0
  197. +f[Matrix.MTRANS_Y];
  198. x[1]=f[Matrix.MSCALE_X]*touchImg.getWidth()+f[Matrix.MSKEW_X]*0
  199. +f[Matrix.MTRANS_X];
  200. y[1]=f[Matrix.MSKEW_Y]*touchImg.getWidth()+f[Matrix.MSCALE_Y]*0
  201. +f[Matrix.MTRANS_Y];
  202. x[2]=f[Matrix.MSCALE_X]*0+f[Matrix.MSKEW_X]
  203. *touchImg.getHeight()+f[Matrix.MTRANS_X];
  204. y[2]=f[Matrix.MSKEW_Y]*0+f[Matrix.MSCALE_Y]
  205. *touchImg.getHeight()+f[Matrix.MTRANS_Y];
  206. x[3]=f[Matrix.MSCALE_X]*touchImg.getWidth()+f[Matrix.MSKEW_X]
  207. *touchImg.getHeight()+f[Matrix.MTRANS_X];
  208. y[3]=f[Matrix.MSKEW_Y]*touchImg.getWidth()+f[Matrix.MSCALE_Y]
  209. *touchImg.getHeight()+f[Matrix.MTRANS_Y];
  210. }
  211. privatefinalstaticintDRAG_LEFT=0;
  212. privatefinalstaticintDRAG_RIGHT=1;
  213. privatefinalstaticintDRAG_TOP=2;
  214. privatefinalstaticintDRAG_DOWN=3;
  215. privatebooleancanDrag(finalintdirection){
  216. float[]x=newfloat[4];
  217. float[]y=newfloat[4];
  218. getFourPoint(x,y);
  219. //出界判断
  220. if((x[0]>0||x[2]>0||x[1]<widthScreen||x[3]<widthScreen)
  221. &&(y[0]>0||y[1]>0||y[2]<heightScreen||y[3]<heightScreen)){
  222. returnfalse;
  223. }
  224. if(DRAG_LEFT==direction){
  225. //左移出界判断
  226. if(x[1]<widthScreen||x[3]<widthScreen){
  227. returnfalse;
  228. }
  229. }elseif(DRAG_RIGHT==direction){
  230. //右移出界判断
  231. if(x[0]>0||x[2]>0){
  232. returnfalse;
  233. }
  234. }elseif(DRAG_TOP==direction){
  235. //上移出界判断
  236. if(y[2]<heightScreen||y[3]<heightScreen){
  237. returnfalse;
  238. }
  239. }elseif(DRAG_DOWN==direction){
  240. //下移出界判断
  241. if(y[0]>0||y[1]>0){
  242. returnfalse;
  243. }
  244. }else{
  245. returnfalse;
  246. }
  247. returntrue;
  248. }
  249. privatebooleancanZoom(){
  250. float[]x=newfloat[4];
  251. float[]y=newfloat[4];
  252. getFourPoint(x,y);
  253. //图片现宽度
  254. doublewidth=Math.sqrt((x[0]-x[1])*(x[0]-x[1])+(y[0]-y[1])
  255. *(y[0]-y[1]));
  256. doubleheight=Math.sqrt((x[0]-x[2])*(x[0]-x[2])+(y[0]-y[2])
  257. *(y[0]-y[2]));
  258. //缩放比率判断
  259. if(width<touchImgWidth*defaultScale-1
  260. ||width>touchImgWidth*MAX_SCALE+1){
  261. returnfalse;
  262. }
  263. //出界判断
  264. if(width<widthScreen&&height<heightScreen){
  265. returnfalse;
  266. }
  267. returntrue;
  268. }
  269. //触碰两点间距离
  270. privatestaticfloatspacing(MotionEventevent){
  271. floatx=event.getX(0)-event.getX(1);
  272. if(x<0){
  273. x=-x;
  274. }
  275. floaty=event.getY(0)-event.getY(1);
  276. if(y<0){
  277. y=-y;
  278. }
  279. returnFloatMath.sqrt(x*x+y*y);
  280. }
  281. //取手势中心点
  282. privatestaticvoidmidPoint(PointFpoint,MotionEventevent){
  283. floatx=event.getX(0)+event.getX(1);
  284. floaty=event.getY(0)+event.getY(1);
  285. point.set(x/2,y/2);
  286. }
  287. //取两点之间的距离
  288. privatestaticfloatdistance(MotionEventpoint2,PointFpoint1){
  289. floatx=point1.x-point2.getX();
  290. if(x<0){
  291. x=-x;
  292. }
  293. floaty=point1.y-point2.getY();
  294. if(y<0){
  295. y=-y;
  296. }
  297. returnFloatMath.sqrt(x*x+y*y);
  298. }
  299. privatevoidchangeSize(floatx,floaty){
  300. if(isBig){
  301. floatsubX=(widthScreen-touchImgWidth*defaultScale)/2;
  302. floatsubY=(heightScreen-touchImgHeight*defaultScale)/2;
  303. preMatrix.reset();
  304. preMatrix.postScale(defaultScale,defaultScale);
  305. preMatrix.postTranslate(subX,subY);
  306. matrix.set(preMatrix);
  307. invalidate();
  308. isBig=false;
  309. }else{
  310. floattransX=(widthScreen-touchImgWidth*MAX_SCALE)/2;
  311. floattransY=(heightScreen-touchImgHeight*MAX_SCALE)/2;
  312. preMatrix.reset();
  313. preMatrix.postScale(MAX_SCALE,MAX_SCALE);
  314. preMatrix.postTranslate(transX,transY);
  315. matrix.set(preMatrix);
  316. invalidate();
  317. isBig=true;
  318. }
  319. }
  320. }
  321. </pre>
  322. <pre></pre>
  323. <pre></pre>
  324. <p></p>
  325. <pre></pre>
  326. <pre></pre>
  327. <p><br>
  328. </p>
  329. <p><br>
  330. </p>
  331. <p></p>
  332. <p>测试代码如下:</p>
  333. <p><br>
  334. </p>
  335. <p>activity_main.xml文件:</p>
  336. <p></p>
  337. <precode_snippet_id="168679"snippet_file_name="blog_20140123_2_8257273"name="code"class="html"><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  338. xmlns:tools="http://schemas.android.com/tools"
  339. android:id="@+id/layout_id"
  340. android:layout_width="match_parent"
  341. android:layout_height="match_parent"
  342. tools:context=".MainActivity">
  343. <com.example.test.TouchImageView
  344. android:id="@+id/img_id"
  345. android:layout_width="400dip"
  346. android:layout_height="800dip"
  347. android:src="@drawable/banner"
  348. android:scaleType="fitCenter"/>
  349. </LinearLayout>
  350. </pre><br>
  351. <p><br>
  352. </p>
  353. <p>MainActivity.java文件:</p>
  354. <p></p>
  355. <p></p>
  356. <precode_snippet_id="168679"snippet_file_name="blog_20140123_3_2367928"name="code"class="java">packagecom.example.test;
  357. importandroid.app.Activity;
  358. importandroid.os.Bundle;
  359. importandroid.util.DisplayMetrics;
  360. importandroid.view.Menu;
  361. importandroid.view.ViewTreeObserver.OnGlobalLayoutListener;
  362. importandroid.widget.LinearLayout;
  363. publicclassMainActivityextendsActivity{
  364. privateTouchImageViewimgView;
  365. @Override
  366. protectedvoidonCreate(BundlesavedInstanceState){
  367. super.onCreate(savedInstanceState);
  368. setContentView(R.layout.activity_main);
  369. DisplayMetricsdm=newDisplayMetrics();
  370. getWindowManager().getDefaultDisplay().getMetrics(dm);
  371. TouchImageViewimgView=(TouchImageView)findViewById(R.id.img_id);
  372. imgView.initImageView(dm.widthPixels,dm.heightPixels-80);
  373. }
  374. @Override
  375. publicbooleanonCreateOptionsMenu(Menumenu){
  376. //Inflatethemenu;thisaddsitemstotheactionbarifitispresent.
  377. getMenuInflater().inflate(R.menu.main,menu);
  378. returntrue;
  379. }
  380. }
  381. </pre><br>
  382. <br>
  383. <p></p>
  384. </pre>

更多相关文章

  1. android – 多屏幕适配相关
  2. Android(安卓)调用微信登陆、支付、分享,出现的白屏、黑屏、闪屏
  3. Android高手进阶教程(十一)--Android(安卓)通用获取Ip的方法(判
  4. Android(安卓)判断应用程序安装位置
  5. Android(安卓)实现图片的自动缩放,适应分辨率不同的手机
  6. Android中实现双指缩放的功能
  7. android判断文件类型是否为音频文件
  8. Android(安卓)上传头像(文件)到服务器
  9. Android和J2ME按钮接口之简单对比

随机推荐

  1. Android 中文API (61) —— ViewSwitcher
  2. 实现录音,播放,以及Socket的上传和下载。。
  3. 手把手教你快速实现Android底部导航栏
  4. Android系统架构基本模式解析
  5. Unity接入Android广告: 二、将Aar包放入Un
  6. android 模拟器横竖屏切换
  7. 一个Android应用程序App中存在多少个Cont
  8. android 反编译的一点思路
  9. Google Android Market电子市场/应用商店
  10. android handler 简介