Android自定义万能Canvas画布

少年意气强不羁,虎胁插翼白日飞。这篇文章主要讲述Android自定义万能Canvas画布相关的知识,希望能为你提供帮助。
一、需求:
1.在自定义的画布中实现可缩放手势,摇一摇可对控件进行整理排序;
2.画布中可以添加位置设定的控件,控件可以响应点击、长按、拖动事件;
3.控件A长按事件会隐藏画布中的控件除了A之外,显示另一个控件B;当A在在底层画布中拖动,拖动结束之后回到原画布;当A移动B的位置范围响应操作(可以添加另方面功能)。
二、实现思想:
1、画布的的手势缩放、控件的添加,在我的上一篇关于画布文章中已经实现了这个功能,这里不再赘述;
2、要实现上述的几个功能只需要屏幕上添加两层画布,一层画布用于添加控件在这层中可以实现控件的点击、拖动、画布缩放、长按事件、整理排序控件。底层画布用于长按其他控件隐藏之后A控件的拖动和B控件的显示及A拖动到B之后的事件响应。
3、当A控件结束拖动(抬起时)回到第一层画布中。
三、效果展示:

Android自定义万能Canvas画布

文章图片

四、具体实现:
【Android自定义万能Canvas画布】1.先添加两层画布用布局可以RelativeLayout包裹着,如:
[html]  view plain  copy    
Android自定义万能Canvas画布

文章图片
Android自定义万能Canvas画布

文章图片
  1. < RelativeLayout   
  2.           android:layout_width="match_parent"   
  3.           android:layout_height="match_parent">    
  4.           < com.view.ActionEditorCanvasView   
  5.                   android:id="@+id/action_editor_canvas_gamepad_test"   
  6.                   android:visibility="gone"   
  7.                   android:layout_width="match_parent"   
  8.                   android:layout_height="match_parent"/>    
  9.           < com.view.ActionEditorCanvasView   
  10.                   android:id="@+id/action_editor_canvas_test"   
  11.                   android:layout_width="match_parent"   
  12.                   android:layout_height="match_parent"/>    
  13.   < /RelativeLayout>    
2.当控件添加到画布中要获取到对应控件的位置信息(将添加的控件添加到一个集合中),判断点击时是否是落在控件之上,这些都是在view中的onTouchEvent(MotionEvent event)进行处理:
 
 
[java]  view plain  copy    
Android自定义万能Canvas画布

文章图片
Android自定义万能Canvas画布

文章图片
  1. private  int  getDown2Widget()  {   
  2.               for  (int  i  =  0;   i  <   mDrawableList.size();   i++)  {   
  3.                       int  xcoords  =  mDrawableList.get(i).getXcoords();    
  4.                       int  ycoords  =  mDrawableList.get(i).getYcoords();    
  5.                       double  abs  =  Math.sqrt((DownX  -  xcoords)  *  (DownX  -  xcoords)  +  (DownY  -  ycoords)  *  (DownY  -  ycoords));    
  6.                       //点落在控件内   
  7.                       if  (abs  <   ActionWidget.RADIUS)  {   
  8.                               return  i;    
  9.                       }   
  10.               }   
  11.               return  -1;    
  12.       }   
3、在画布中实现Move、LongPress、Up、Click的接口回调用于对外应用:
 
 
[java]  view plain  copy    
Android自定义万能Canvas画布

文章图片
Android自定义万能Canvas画布

文章图片
  1. public  onWidgetUpListener  mOnWidgetUpListener;    
  2. public  interface  onWidgetUpListener{   
  3.         void  onWidgetUp(int  index,int  x,int  y);    
  4. }   
  5.    
  6. public  void    setOnWidgetUpListener(onWidgetUpListener  mOnWidgetUpListener){   
  7.         this.mOnWidgetUpListener=mOnWidgetUpListener;    
  8. }   
  9.    
  10. public  onWidgetMoveListener  mOnWidgetMoveListener;    
  11.    
  12. public  interface  onWidgetMoveListener{   
  13.           void  onWidgetMove(int  index,int  x,int  y);    
  14. }   
  15.    
  16. public  void    setOnWidgetMoveListener(onWidgetMoveListener  moveListener){   
  17.         this.mOnWidgetMoveListener=moveListener;    
  18. }   
  19.    
  20. public  onWidgetLongPressListener  mOnWidgetLongPressListener;    
  21.    
  22. public  interface  onWidgetLongPressListener{   
  23.         void  onWidgetLongPress(int  index,int  x,int  y);    
  24. }   
  25.    
  26. public  void  setOnWidgetLongPressListener(onWidgetLongPressListener  mOnWidgetLongPressListener){   
  27.         this.mOnWidgetLongPressListener=mOnWidgetLongPressListener;    
  28. }   
  29.    
  30.    
  31. public  onWidgetClickListener  mOnWidgetClickListener;    
  32.    
  33. public  interface  onWidgetClickListener{   
  34.         void  onWidgetClick(int  index,int  x,int  y);    
  35. }   
  36.    
  37. public  void  setOnWidgetClickListener(onWidgetClickListener  mOnWidgetClickListener){   
  38.         this.mOnWidgetClickListener=mOnWidgetClickListener;    
  39. }   
4.接下来就是处理拖动、点击、长按、抬起的事件的处理:


[java]  view plain  copy    
Android自定义万能Canvas画布

文章图片
Android自定义万能Canvas画布

文章图片
  1. public  boolean  onTouchEvent(MotionEvent  event)  {                 
  2.               switch  (event.getAction())  {   
  3.                       case  MotionEvent.ACTION_DOWN:  {   
  4.                               mDownTime  =  System.currentTimeMillis();    
  5.                               DownX  =  event.getX(); //float  DownX   
  6.                               DownY  =  event.getY(); //float  DownY   
  7.                               //判断点击的坐标范围是否在控件上   
  8.                               mDown2Widget  =  getDown2Widget();    
  9.                               moveX  =  0;    
  10.                               moveY  =  0;    
  11.                               moveX1  =  0;    
  12.                               moveY1  =  0;    
  13.                       }   
  14.                       break;    
  15.                       case  MotionEvent.ACTION_MOVE:  {   
  16.                               moveX  +=  Math.abs(event.getX()  -  DownX); //X轴距离   
  17.                               moveY  +=  Math.abs(event.getY()  -  DownY); //y轴距离   
  18.                               moveX1  =  event.getX();    
  19.                               moveY1  =  event.getY();    
  20.                               if  (moveX  ==  0  & &   moveY  ==  0)  {   
  21.                                       mMoveTime  =  System.currentTimeMillis();    
  22.                                       long  DValueTime  =  mMoveTime  -  mDownTime; //计算点击下去是否有移动及事件是否符合长按的时间值,这样可以判断是否是长按事件   
  23.                                       if  (DValueTime> 200){< span  style="white-space:pre">         < /span>    
  24.                                               if  (mOnWidgetLongPressListener!=null){   
  25.                                                       mOnWidgetLongPressListener.onWidgetLongPress(mDown2Widget,(int)moveX1,(int)moveY1);    
  26.                                               }   
  27.                                       }   
  28.                                       return  true;    
  29.                               }  else  {   
  30.                                       if  (mDown2Widget  >   -1)  {   
  31.                                               if  (mOnWidgetMoveListener!=null){   
  32.                                                       mOnWidgetMoveListener.onWidgetMove(mDown2Widget,(int)moveX1,(int)moveY1);    
  33.                                               }   
  34.                                               mDrawableList.get(mDown2Widget).setXcoords((int)  moveX1); //点击在控件之上进行的move则把控件坐标值重置,从而是实现控件拖动   
  35.                                               mDrawableList.get(mDown2Widget).setYcoords((int)  moveY1);    
  36.                                               invalidate();    
  37.                                       }   
  38.                               }   
  39.                               DownX  =  event.getX();    
  40.                               DownY  =  event.getY();    
  41.                       }   
  42.                       break;    
  43.                       case  MotionEvent.ACTION_UP:  {   
  44.                               long  moveTime  =  System.currentTimeMillis()  -  currentMS; //移动时间   
  45.                               mUpTime  =  System.currentTimeMillis();    
  46.                               long  DValueTime  =  mUpTime  -  mDownTime; //判断从按下到抬起的实现,从而实现判断是否是点击   
  47.                               if  (mDown2Widget  >   -1)  {   
  48.                                       //判断是否为拖动事件   
  49.                                       if  (!(moveTime  >   1000  & &   (moveX  >   100  ||  moveY  >   100)))  {   
  50.                                               if  (DValueTime  <   200)  {   
  51.                                                       if  (mOnWidgetClickListener!=null){   
  52.                                                               mOnWidgetClickListener.onWidgetClick(mDown2Widget,(int)moveX1,(int)moveY1);    
  53.                                                       }   
  54.                                               }   
  55.                                       }   
  56.                               }   
  57.                               if  (mOnWidgetUpListener!=null){//判断是否是抬起事件   
  58.                                       mOnWidgetUpListener.onWidgetUp(mDown2Widget,(int)moveX1,(int)moveY1);    
  59.                               }   
  60.                       }   
  61.                       break;    
  62.               }   
  63.               return  true;    
  64.    
  65.       }   

5、在底层画布添加控件B,并获取位置信息存起来:
 
 
[java]  view plain  copy    
Android自定义万能Canvas画布

文章图片
Android自定义万能Canvas画布

文章图片
  1. mBitmap=  BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);    
  2. mGamePadBitmap=new  CBitmap(mBitmap,200,1000);    
  3. mXcoords  =  mGamePadBitmap.getXcoords();    
  4. mYcoords  =  mGamePadBitmap.getYcoords();    
  5. mGamePadCanvasView.addCanvasDrawable(mGamePadBitmap);    

6、处理长按事件,隐藏第一层画布显示底层画布,并获取A控件位置在底层画布中画出来:
 
 
[java]  view plain  copy    
Android自定义万能Canvas画布

文章图片
Android自定义万能Canvas画布

文章图片
  1. mCanvasView.setOnWidgetLongPressListener(new  ActionEditorCanvasView.onWidgetLongPressListener()  {   
  2.           @Override   
  3.           public  void  onWidgetLongPress(int  index,  int  x,  int  y)  {   
  4.                   ActionWidget  actionWidget  =  (ActionWidget)  mCanvasView.mDrawableList.get(index);    
  5.                   mCanvasView.setVisibility(View.GONE);    
  6.                   mGamePadCanvasView.setVisibility(View.VISIBLE);    
  7.                   mGamePadWidget=new  ActionWidget(x,  y,  mPaint);    
  8.                   mGamePadCanvasView.addCanvasDrawable(mGamePadWidget);    
  9.                   isGamePadCanvas=true; //把是否显示底层画布的开关开启   
  10.           }   
  11.   });    
7、判断A控件是否移动B控件的位置范围之上:
 
 
[java]  view plain  copy    
Android自定义万能Canvas画布

文章图片
Android自定义万能Canvas画布

文章图片
  1. mCanvasView.setOnWidgetMoveListener(new  ActionEditorCanvasView.onWidgetMoveListener()  {   
  2.                         @Override   
  3.                         public  void  onWidgetMove(int  index,  int  x,  int  y)  {   
  4.                                 if  (isGamePadCanvas){   
  5.                                         if  (mGamePadWidget!=null){   
  6.                                                 mGamePadCanvasView.mDrawableList.get(1).setXcoords(x);    
  7.                                                 mGamePadCanvasView.mDrawableList.get(1).setYcoords(y);    
  8.                                                 mGamePadCanvasView.invalidate();    
  9.                                                 if  ((x> mXcoords& & x< mXcoords+250)& & (y> mYcoords& & y< mYcoords+250)){   
  10.                                                         Toast.makeText(ActionCanvasTestActivity.this,  "控件移动到控制器按钮界面!!!!!"  ,  Toast.LENGTH_SHORT).show();    
  11.                                                 }   
  12.                                         }   
  13.                               }   
  14.                         }   
  15.                 });    
8、最后是判断抬起事件,如底层画布是显示则隐藏底层画布显示第一层画布:
[java]  view plain  copy    
Android自定义万能Canvas画布

文章图片
Android自定义万能Canvas画布

文章图片
  1. mCanvasView.setOnWidgetUpListener(new  ActionEditorCanvasView.onWidgetUpListener()  {   
  2.             @Override   
  3.             public  void  onWidgetUp(int  index,  int  x,  int  y)  {   
  4.                     if  (isGamePadCanvas){   
  5.                             mCanvasView.setVisibility(View.VISIBLE);    
  6.                             mGamePadCanvasView.setVisibility(View.GONE);    
  7.                             mGamePadCanvasView.mDrawableList.remove(1);    
  8.                             isGamePadCanvas=false;    
  9.                     }   
  10.             }   
  11.     });    
 
五、Demo项目地址:http://download.csdn.net/download/wangyongyao1989/9901019





    推荐阅读