Android自定義萬能Canvas畫布


一、需求:

1.在自定義的畫布中實現可縮放手勢,搖一搖可對控件進行整理排序;

2.畫布中可以添加位置設定的控件,控件可以響應點擊、長按、拖動事件;

3.控件A長按事件會隱藏畫布中的控件除了A之外,顯示另一個控件B;當A在在底層畫布中拖動,拖動結束之后回到原畫布;當A移動B的位置范圍響應操作(可以添加另方面功能)。

二、實現思想:

1、畫布的的手勢縮放、控件的添加,在我的上一篇關於畫布文章中已經實現了這個功能,這里不再贅述;

2、要實現上述的幾個功能只需要屏幕上添加兩層畫布,一層畫布用於添加控件在這層中可以實現控件的點擊、拖動、畫布縮放、長按事件、整理排序控件。底層畫布用於長按其他控件隱藏之后A控件的拖動和B控件的顯示及A拖動到B之后的事件響應。

3、當A控件結束拖動(抬起時)回到第一層畫布中。

三、效果展示:

四、具體實現:

1.先添加兩層畫布用布局可以RelativeLayout包裹着,如:

[html]  view plain  copy
 
 在CODE上查看代碼片派生到我的代碼片
  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
 
 在CODE上查看代碼片派生到我的代碼片
  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
 
 在CODE上查看代碼片派生到我的代碼片
  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
 
 在CODE上查看代碼片派生到我的代碼片
  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
 
 在CODE上查看代碼片派生到我的代碼片
  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
 
 在CODE上查看代碼片派生到我的代碼片
  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
 
 在CODE上查看代碼片派生到我的代碼片
  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
 
 在CODE上查看代碼片派生到我的代碼片
  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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM