本文主要讲解利用android中Matrix控制图形的旋转缩放移动,具体参见一下代码:

view plainprint?
  1. /**
  2. *使用矩阵控制图片移动、缩放、旋转
  3. *@author张进
  4. */
  5. publicclassCommonImgEffectViewextendsView{
  6. privateContextcontext;
  7. privateBitmapmainBmp,controlBmp;
  8. privateintmainBmpWidth,mainBmpHeight,controlBmpWidth,controlBmpHeight;
  9. privateMatrixmatrix;
  10. privatefloat[]srcPs,dstPs;
  11. privateRectFsrcRect,dstRect;
  12. privatePaintpaint,paintRect,paintFrame;
  13. privatefloatdeltaX=0,deltaY=0;//位移值
  14. privatefloatscaleValue=1;//缩放值
  15. privatePointlastPoint;
  16. privatePointprePivot,lastPivot;
  17. privatefloatpreDegree,lastDegree;
  18. privateshortcurrentSelectedPointindex;//当前操作点击点
  19. privatePointsymmetricPoint=newPoint();//当前操作点对称点
  20. /**
  21. *图片操作类型
  22. */
  23. publicstaticfinalintOPER_DEFAULT=-1;//默认
  24. publicstaticfinalintOPER_TRANSLATE=0;//移动
  25. publicstaticfinalintOPER_SCALE=1;//缩放
  26. publicstaticfinalintOPER_ROTATE=2;//旋转
  27. publicstaticfinalintOPER_SELECTED=3;//选择
  28. publicintlastOper=OPER_DEFAULT;
  29. /*图片控制点
  30. *0---1---2
  31. *||
  32. *783
  33. *||
  34. *6---5---4
  35. */
  36. publicstaticfinalintCTR_NONE=-1;
  37. publicstaticfinalintCTR_LEFT_TOP=0;
  38. publicstaticfinalintCTR_MID_TOP=1;
  39. publicstaticfinalintCTR_RIGHT_TOP=2;
  40. publicstaticfinalintCTR_RIGHT_MID=3;
  41. publicstaticfinalintCTR_RIGHT_BOTTOM=4;
  42. publicstaticfinalintCTR_MID_BOTTOM=5;
  43. publicstaticfinalintCTR_LEFT_BOTTOM=6;
  44. publicstaticfinalintCTR_LEFT_MID=7;
  45. publicstaticfinalintCTR_MID_MID=8;
  46. publicintcurrent_ctr=CTR_NONE;
  47. publicCommonImgEffectView(Contextcontext){
  48. super(context);
  49. this.context=context;
  50. }
  51. publicCommonImgEffectView(Contextcontext,AttributeSetattrs){
  52. super(context,attrs);
  53. this.context=context;
  54. initData();
  55. }
  56. /**
  57. *初始化数据
  58. *@author张进
  59. */
  60. privatevoidinitData(){
  61. mainBmp=BitmapFactory.decodeResource(this.context.getResources(),R.drawable.flower);
  62. controlBmp=BitmapFactory.decodeResource(this.context.getResources(),R.drawable.control);
  63. mainBmpWidth=mainBmp.getWidth();
  64. mainBmpHeight=mainBmp.getHeight();
  65. controlBmpWidth=controlBmp.getWidth();
  66. controlBmpHeight=controlBmp.getHeight();
  67. srcPs=newfloat[]{
  68. 0,0,
  69. mainBmpWidth/2,0,
  70. mainBmpWidth,0,
  71. mainBmpWidth,mainBmpHeight/2,
  72. mainBmpWidth,mainBmpHeight,
  73. mainBmpWidth/2,mainBmpHeight,
  74. 0,mainBmpHeight,
  75. 0,mainBmpHeight/2,
  76. mainBmpWidth/2,mainBmpHeight/2
  77. };
  78. dstPs=srcPs.clone();
  79. srcRect=newRectF(0,0,mainBmpWidth,mainBmpHeight);
  80. dstRect=newRectF();
  81. matrix=newMatrix();
  82. prePivot=newPoint(mainBmpWidth/2,mainBmpHeight/2);
  83. lastPivot=newPoint(mainBmpWidth/2,mainBmpHeight/2);
  84. lastPoint=newPoint(0,0);
  85. paint=newPaint();
  86. paintRect=newPaint();
  87. paintRect.setColor(Color.RED);
  88. paintRect.setAlpha(100);
  89. paintRect.setAntiAlias(true);
  90. paintFrame=newPaint();
  91. paintFrame.setColor(Color.GREEN);
  92. paintFrame.setAntiAlias(true);
  93. setMatrix(OPER_DEFAULT);
  94. }
  95. /**
  96. *矩阵变换,达到图形平移的目的
  97. *@author张进
  98. */
  99. privatevoidsetMatrix(intoperationType){
  100. switch(operationType){
  101. caseOPER_TRANSLATE:
  102. matrix.postTranslate(deltaX,deltaY);
  103. break;
  104. caseOPER_SCALE:
  105. matrix.postScale(scaleValue,scaleValue,symmetricPoint.x,symmetricPoint.y);
  106. break;
  107. caseOPER_ROTATE:
  108. matrix.postRotate(preDegree-lastDegree,dstPs[CTR_MID_MID*2],dstPs[CTR_MID_MID*2+1]);
  109. break;
  110. }
  111. matrix.mapPoints(dstPs,srcPs);
  112. matrix.mapRect(dstRect,srcRect);
  113. }
  114. privatebooleanisOnPic(intx,inty){
  115. if(dstRect.contains(x,y)){
  116. returntrue;
  117. }else
  118. returnfalse;
  119. }
  120. privateintgetOperationType(MotionEventevent){
  121. intevX=(int)event.getX();
  122. intevY=(int)event.getY();
  123. intcurOper=lastOper;
  124. switch(event.getAction()){
  125. caseMotionEvent.ACTION_DOWN:
  126. current_ctr=isOnCP(evX,evY);
  127. Log.i("img","current_ctris"+current_ctr);
  128. if(current_ctr!=CTR_NONE||isOnPic(evX,evY)){
  129. curOper=OPER_SELECTED;
  130. }
  131. break;
  132. caseMotionEvent.ACTION_MOVE:
  133. if(current_ctr>CTR_NONE&&current_ctr<CTR_MID_MID){
  134. curOper=OPER_SCALE;
  135. }elseif(current_ctr==CTR_MID_MID){
  136. curOper=OPER_ROTATE;
  137. }elseif(lastOper==OPER_SELECTED){
  138. curOper=OPER_TRANSLATE;
  139. }
  140. break;
  141. caseMotionEvent.ACTION_UP:
  142. curOper=OPER_SELECTED;
  143. break;
  144. default:
  145. break;
  146. }
  147. Log.d("img","curOperis"+curOper);
  148. returncurOper;
  149. }
  150. /**
  151. *判断点所在的控制点
  152. *@paramevX
  153. *@paramevY
  154. *@return
  155. */
  156. privateintisOnCP(intevx,intevy){
  157. Rectrect=newRect(evx-controlBmpWidth/2,evy-controlBmpHeight/2,evx+controlBmpWidth/2,evy+controlBmpHeight/2);
  158. intres=0;
  159. for(inti=0;i<dstPs.length;i+=2){
  160. if(rect.contains((int)dstPs[i],(int)dstPs[i+1])){
  161. returnres;
  162. }
  163. ++res;
  164. }
  165. returnCTR_NONE;
  166. }
  167. @Override
  168. publicbooleandispatchTouchEvent(MotionEventevent){
  169. intevX=(int)event.getX();
  170. intevY=(int)event.getY();
  171. intoperType=OPER_DEFAULT;
  172. operType=getOperationType(event);
  173. switch(operType){
  174. caseOPER_TRANSLATE:
  175. translate(evX,evY);
  176. break;
  177. caseOPER_SCALE:
  178. scale(event);
  179. break;
  180. caseOPER_ROTATE:
  181. rotate(event);
  182. break;
  183. }
  184. lastPoint.x=evX;
  185. lastPoint.y=evY;
  186. lastOper=operType;
  187. invalidate();//重绘
  188. returntrue;
  189. }
  190. /**
  191. *移动
  192. *@paramevx
  193. *@paramevy
  194. *@authorzhang_jin1
  195. */
  196. privatevoidtranslate(intevx,intevy){
  197. prePivot.x+=evx-lastPoint.x;
  198. prePivot.y+=evy-lastPoint.y;
  199. deltaX=prePivot.x-lastPivot.x;
  200. deltaY=prePivot.y-lastPivot.y;
  201. lastPivot.x=prePivot.x;
  202. lastPivot.y=prePivot.y;
  203. setMatrix(OPER_TRANSLATE);//设置矩阵
  204. }
  205. /**
  206. *缩放
  207. *0---1---2
  208. *||
  209. *783
  210. *||
  211. *6---5---4
  212. *@paramevX
  213. *@paramevY
  214. */
  215. privatevoidscale(MotionEventevent){
  216. intpointIndex=current_ctr*2;
  217. floatpx=dstPs[pointIndex];
  218. floatpy=dstPs[pointIndex+1];
  219. floatevx=event.getX();
  220. floatevy=event.getY();
  221. floatoppositeX=0;
  222. floatoppositeY=0;
  223. if(current_ctr<4&&current_ctr>=0){
  224. oppositeX=dstPs[pointIndex+8];
  225. oppositeY=dstPs[pointIndex+9];
  226. }elseif(current_ctr>=4){
  227. oppositeX=dstPs[pointIndex-8];
  228. oppositeY=dstPs[pointIndex-7];
  229. }
  230. floattemp1=getDistanceOfTwoPoints(px,py,oppositeX,oppositeY);
  231. floattemp2=getDistanceOfTwoPoints(evx,evy,oppositeX,oppositeY);
  232. this.scaleValue=temp2/temp1;
  233. symmetricPoint.x=(int)oppositeX;
  234. symmetricPoint.y=(int)oppositeY;
  235. Log.i("img","scaleValueis"+scaleValue);
  236. setMatrix(OPER_SCALE);
  237. }
  238. /**
  239. *旋转图片
  240. *0---1---2
  241. *||
  242. *783
  243. *||
  244. *6---5---4
  245. *@paramevX
  246. *@paramevY
  247. */
  248. privatevoidrotate(MotionEventevent){
  249. if(event.getPointerCount()==2){
  250. preDegree=computeDegree(newPoint((int)event.getX(0),(int)event.getY(0)),newPoint((int)event.getX(1),(int)event.getY(1)));
  251. }else{
  252. preDegree=computeDegree(newPoint((int)event.getX(),(int)event.getY()),newPoint((int)dstPs[16],(int)dstPs[17]));
  253. }
  254. setMatrix(OPER_ROTATE);
  255. lastDegree=preDegree;
  256. }
  257. /**
  258. *计算两点与垂直方向夹角
  259. *@paramp1
  260. *@paramp2
  261. *@return
  262. */
  263. publicfloatcomputeDegree(Pointp1,Pointp2){
  264. floattran_x=p1.x-p2.x;
  265. floattran_y=p1.y-p2.y;
  266. floatdegree=0.0f;
  267. floatangle=(float)(Math.asin(tran_x/Math.sqrt(tran_x*tran_x+tran_y*tran_y))*180/Math.PI);
  268. if(!Float.isNaN(angle)){
  269. if(tran_x>=0&&tran_y<=0){//第一象限
  270. degree=angle;
  271. }elseif(tran_x<=0&&tran_y<=0){//第二象限
  272. degree=angle;
  273. }elseif(tran_x<=0&&tran_y>=0){//第三象限
  274. degree=-180-angle;
  275. }elseif(tran_x>=0&&tran_y>=0){//第四象限
  276. degree=180-angle;
  277. }
  278. }
  279. returndegree;
  280. }
  281. /**
  282. *计算两个点之间的距离
  283. *@paramp1
  284. *@paramp2
  285. *@return
  286. */
  287. privatefloatgetDistanceOfTwoPoints(Pointp1,Pointp2){
  288. return(float)(Math.sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));
  289. }
  290. privatefloatgetDistanceOfTwoPoints(floatx1,floaty1,floatx2,floaty2){
  291. return(float)(Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
  292. }
  293. @Override
  294. publicvoidonDraw(Canvascanvas){
  295. drawBackground(canvas);//绘制背景,以便测试矩形的映射
  296. canvas.drawBitmap(mainBmp,matrix,paint);//绘制主图片
  297. drawFrame(canvas);//绘制边框,以便测试点的映射
  298. drawControlPoints(canvas);//绘制控制点图片
  299. }
  300. privatevoiddrawBackground(Canvascanvas){
  301. canvas.drawRect(dstRect,paintRect);
  302. }
  303. privatevoiddrawFrame(Canvascanvas){
  304. canvas.drawLine(dstPs[0],dstPs[1],dstPs[4],dstPs[5],paintFrame);
  305. canvas.drawLine(dstPs[4],dstPs[5],dstPs[8],dstPs[9],paintFrame);
  306. canvas.drawLine(dstPs[8],dstPs[9],dstPs[12],dstPs[13],paintFrame);
  307. canvas.drawLine(dstPs[0],dstPs[1],dstPs[12],dstPs[13],paintFrame);
  308. canvas.drawPoint(dstPs[16],dstPs[17],paintFrame);
  309. }
  310. privatevoiddrawControlPoints(Canvascanvas){
  311. for(inti=0;i<dstPs.length;i+=2){
  312. canvas.drawBitmap(controlBmp,dstPs[i]-controlBmpWidth/2,dstPs[i+1]-controlBmpHeight/2,paint);
  313. }
  314. }
  315. }

Demo效果:


更多相关文章

  1. Android(安卓)使用Vitamio实现播放视频(一)
  2. Android(安卓)图形学原理之OpenGL ES
  3. android图片缩放(指定大小)
  4. 优化布局在Android–减少过度渲染
  5. android图片缩放(指定大小)
  6. android 生成圆角和带倒影图片
  7. android 按钮的点击缩放
  8. Android(安卓)图片缩放实例详解
  9. android获取图库图片并返回

随机推荐

  1. Android Studio 开发常用快捷键
  2. Android 应用程序签名
  3. Android 禁止带有home属性的APP安装
  4. android基础之Application
  5. android 设置中文字体。。。。
  6. android 各版本发布时间
  7. Android Studio 更新中的问题
  8. Android设置默认时间
  9. SeekBar自定义样式
  10. Android 一些注意