一、需求:
1.在自定義的畫布中實現可縮放手勢,搖一搖可對控件進行整理排序;
2.畫布中可以添加位置設定的控件,控件可以響應點擊、長按、拖動事件;
3.控件A長按事件會隱藏畫布中的控件除了A之外,顯示另一個控件B;當A在在底層畫布中拖動,拖動結束之后回到原畫布;當A移動B的位置范圍響應操作(可以添加另方面功能)。
二、實現思想:
1、畫布的的手勢縮放、控件的添加,在我的上一篇關於畫布文章中已經實現了這個功能,這里不再贅述;
2、要實現上述的幾個功能只需要屏幕上添加兩層畫布,一層畫布用於添加控件在這層中可以實現控件的點擊、拖動、畫布縮放、長按事件、整理排序控件。底層畫布用於長按其他控件隱藏之后A控件的拖動和B控件的顯示及A拖動到B之后的事件響應。
3、當A控件結束拖動(抬起時)回到第一層畫布中。
三、效果展示:
四、具體實現:
1.先添加兩層畫布用布局可以RelativeLayout包裹着,如:
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <com.view.ActionEditorCanvasView
- android:id="@+id/action_editor_canvas_gamepad_test"
- android:visibility="gone"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
- <com.view.ActionEditorCanvasView
- android:id="@+id/action_editor_canvas_test"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
- </RelativeLayout>
2.當控件添加到畫布中要獲取到對應控件的位置信息(將添加的控件添加到一個集合中),判斷點擊時是否是落在控件之上,這些都是在view中的onTouchEvent(MotionEvent event)進行處理:
- private int getDown2Widget() {
- for (int i = 0; i < mDrawableList.size(); i++) {
- int xcoords = mDrawableList.get(i).getXcoords();
- int ycoords = mDrawableList.get(i).getYcoords();
- double abs = Math.sqrt((DownX - xcoords) * (DownX - xcoords) + (DownY - ycoords) * (DownY - ycoords));
- //點落在控件內
- if (abs < ActionWidget.RADIUS) {
- return i;
- }
- }
- return -1;
- }
3、在畫布中實現Move、LongPress、Up、Click的接口回調用於對外應用:
- public onWidgetUpListener mOnWidgetUpListener;
- public interface onWidgetUpListener{
- void onWidgetUp(int index,int x,int y);
- }
- public void setOnWidgetUpListener(onWidgetUpListener mOnWidgetUpListener){
- this.mOnWidgetUpListener=mOnWidgetUpListener;
- }
- public onWidgetMoveListener mOnWidgetMoveListener;
- public interface onWidgetMoveListener{
- void onWidgetMove(int index,int x,int y);
- }
- public void setOnWidgetMoveListener(onWidgetMoveListener moveListener){
- this.mOnWidgetMoveListener=moveListener;
- }
- public onWidgetLongPressListener mOnWidgetLongPressListener;
- public interface onWidgetLongPressListener{
- void onWidgetLongPress(int index,int x,int y);
- }
- public void setOnWidgetLongPressListener(onWidgetLongPressListener mOnWidgetLongPressListener){
- this.mOnWidgetLongPressListener=mOnWidgetLongPressListener;
- }
- public onWidgetClickListener mOnWidgetClickListener;
- public interface onWidgetClickListener{
- void onWidgetClick(int index,int x,int y);
- }
- public void setOnWidgetClickListener(onWidgetClickListener mOnWidgetClickListener){
- this.mOnWidgetClickListener=mOnWidgetClickListener;
- }
4.接下來就是處理拖動、點擊、長按、抬起的事件的處理:
- public boolean onTouchEvent(MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN: {
- mDownTime = System.currentTimeMillis();
- DownX = event.getX();//float DownX
- DownY = event.getY();//float DownY
- //判斷點擊的坐標范圍是否在控件上
- mDown2Widget = getDown2Widget();
- moveX = 0;
- moveY = 0;
- moveX1 = 0;
- moveY1 = 0;
- }
- break;
- case MotionEvent.ACTION_MOVE: {
- moveX += Math.abs(event.getX() - DownX);//X軸距離
- moveY += Math.abs(event.getY() - DownY);//y軸距離
- moveX1 = event.getX();
- moveY1 = event.getY();
- if (moveX == 0 && moveY == 0) {
- mMoveTime = System.currentTimeMillis();
- long DValueTime = mMoveTime - mDownTime;//計算點擊下去是否有移動及事件是否符合長按的時間值,這樣可以判斷是否是長按事件
- if (DValueTime>200){<span style="white-space:pre"> </span>
- if (mOnWidgetLongPressListener!=null){
- mOnWidgetLongPressListener.onWidgetLongPress(mDown2Widget,(int)moveX1,(int)moveY1);
- }
- }
- return true;
- } else {
- if (mDown2Widget > -1) {
- if (mOnWidgetMoveListener!=null){
- mOnWidgetMoveListener.onWidgetMove(mDown2Widget,(int)moveX1,(int)moveY1);
- }
- mDrawableList.get(mDown2Widget).setXcoords((int) moveX1);//點擊在控件之上進行的move則把控件坐標值重置,從而是實現控件拖動
- mDrawableList.get(mDown2Widget).setYcoords((int) moveY1);
- invalidate();
- }
- }
- DownX = event.getX();
- DownY = event.getY();
- }
- break;
- case MotionEvent.ACTION_UP: {
- long moveTime = System.currentTimeMillis() - currentMS;//移動時間
- mUpTime = System.currentTimeMillis();
- long DValueTime = mUpTime - mDownTime;//判斷從按下到抬起的實現,從而實現判斷是否是點擊
- if (mDown2Widget > -1) {
- //判斷是否為拖動事件
- if (!(moveTime > 1000 && (moveX > 100 || moveY > 100))) {
- if (DValueTime < 200) {
- if (mOnWidgetClickListener!=null){
- mOnWidgetClickListener.onWidgetClick(mDown2Widget,(int)moveX1,(int)moveY1);
- }
- }
- }
- }
- if (mOnWidgetUpListener!=null){//判斷是否是抬起事件
- mOnWidgetUpListener.onWidgetUp(mDown2Widget,(int)moveX1,(int)moveY1);
- }
- }
- break;
- }
- return true;
- }
5、在底層畫布添加控件B,並獲取位置信息存起來:
- mBitmap= BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
- mGamePadBitmap=new CBitmap(mBitmap,200,1000);
- mXcoords = mGamePadBitmap.getXcoords();
- mYcoords = mGamePadBitmap.getYcoords();
- mGamePadCanvasView.addCanvasDrawable(mGamePadBitmap);
6、處理長按事件,隱藏第一層畫布顯示底層畫布,並獲取A控件位置在底層畫布中畫出來:
- mCanvasView.setOnWidgetLongPressListener(new ActionEditorCanvasView.onWidgetLongPressListener() {
- @Override
- public void onWidgetLongPress(int index, int x, int y) {
- ActionWidget actionWidget = (ActionWidget) mCanvasView.mDrawableList.get(index);
- mCanvasView.setVisibility(View.GONE);
- mGamePadCanvasView.setVisibility(View.VISIBLE);
- mGamePadWidget=new ActionWidget(x, y, mPaint);
- mGamePadCanvasView.addCanvasDrawable(mGamePadWidget);
- isGamePadCanvas=true;//把是否顯示底層畫布的開關開啟
- }
- });
7、判斷A控件是否移動B控件的位置范圍之上:
- mCanvasView.setOnWidgetMoveListener(new ActionEditorCanvasView.onWidgetMoveListener() {
- @Override
- public void onWidgetMove(int index, int x, int y) {
- if (isGamePadCanvas){
- if (mGamePadWidget!=null){
- mGamePadCanvasView.mDrawableList.get(1).setXcoords(x);
- mGamePadCanvasView.mDrawableList.get(1).setYcoords(y);
- mGamePadCanvasView.invalidate();
- if ((x>mXcoords&&x<mXcoords+250)&&(y>mYcoords&&y<mYcoords+250)){
- Toast.makeText(ActionCanvasTestActivity.this, "控件移動到控制器按鈕界面!!!!!" , Toast.LENGTH_SHORT).show();
- }
- }
- }
- }
- });
8、最后是判斷抬起事件,如底層畫布是顯示則隱藏底層畫布顯示第一層畫布:
- mCanvasView.setOnWidgetUpListener(new ActionEditorCanvasView.onWidgetUpListener() {
- @Override
- public void onWidgetUp(int index, int x, int y) {
- if (isGamePadCanvas){
- mCanvasView.setVisibility(View.VISIBLE);
- mGamePadCanvasView.setVisibility(View.GONE);
- mGamePadCanvasView.mDrawableList.remove(1);
- isGamePadCanvas=false;
- }
- }
- });
五、Demo項目地址:http://download.csdn.net/download/wangyongyao1989/9901019