Android自定义View的多点触控
生活随笔
收集整理的這篇文章主要介紹了
Android自定义View的多点触控
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
在Android游戲開發中,自定義View的多點觸控技術必不可少,本文主要簡單講解下Android中多點觸控技術的基礎知識。
所謂多點觸控技術,就是手機屏幕上支持同時處理多個觸控點的觸屏或移動事件。多點觸控的關鍵點有以下三點:(1)需要LCD和應用程序同時支持;(2)通過重寫View類中的onTouchEvent()方法來實現;(3)通過event.getActionMasked()來判斷觸控點的性質(主控點/輔控點)和動作類型(按下/移動/抬起).
對于單點觸控,MotionEvent的類型常量及含義如下:
MotionEvent.ACTION_DOWN://觸控點按下
MotionEvent.ACTION_MOVE://觸控點移動
MotionEvent.ACTION_UP://觸控點抬起
對于多點觸控,MotionEvent的類型常量及含義如下:
MotionEvent.ACTION_DOWN://(主控點)第一個觸控點按下
MotionEvent.ACTION_POINTER_DOWN://(輔控點)第一個之后的觸控點按下
MotionEvent.ACTION_MOVE://主、輔控點移動
MotionEvent.ACTION_UP://最后一個觸控點抬起
MotionEvent.ACTION_POINTER_UP://非最后一個觸控點抬起
值得注意的是,對于多點觸控,主/輔控點的按下或抬起的事件都是針對一個觸控點的,也就是說可以通過與運算和移位運算獲得本次觸控事件的觸點id:
int id = (event.getAction()&MotionEvent.ACTION_POINTER_ID_MASK) >>> MotionEvent.ACTION_POINTER_ID_SHIFT;
而主/輔控點的移動事件則更多的是針對所有觸控點的,即event中包含了本次采樣時獲得的所有觸控點移動后的坐標,因此,在移動事件中,通常需要對所有的觸控點進行相應的邏輯處理。
以下是一個簡單的多點觸控例子。(1)觸控點的描述類
簡單地,觸控點需要描述其坐標和id,本例中再加上觸控點的繪制半徑和顏色。
public class BNPoint {float x;//觸控點x坐標float y;//觸控點y坐標int id;//觸控點idint[] color;//觸控點的繪制顏色static final float RADIS = 80;//觸控點繪制半徑public BNPoint(float x,float y,int[] color,int id){this.x = x;this.y = y;this.color = color;this.id = id;}public void setLocation(float x,float y){this.x = x;this.y = y;}public void drawSelf(Paint paint, Paint paint1, Canvas canvas){paint.setARGB(180,color[1],color[2],color[3]);canvas.drawCircle(x,y,RADIS,paint);//繪制最外層的圓環paint.setARGB(150,color[1],color[2],color[3]);canvas.drawCircle(x,y,RADIS-10,paint);//繪制中間的圓環canvas.drawCircle(x,y,RADIS-18,paint1);canvas.drawText(id+"",x,y-100,paint1);//繪制id}
}
(2)繪圖類
繪圖類主要處理所有觸控點的動作事件,維護觸控點列表,并繪制所有觸控點。
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {private MainActivity activity;private Paint paint;//畫筆private Paint paint1;private ArrayList<BNPoint> pointArrayList = new ArrayList<>();//觸控點列表public MySurfaceView(MainActivity activity){super(activity);this.activity = activity;this.getHolder().addCallback(this);paint = new Paint();paint.setAntiAlias(true);paint1 = new Paint();paint1.setAntiAlias(true);paint1.setTextSize(35);}public void onDraw(Canvas canvas){canvas.drawColor(Color.BLACK);paint.setStrokeWidth(10);paint.setStyle(Paint.Style.STROKE);paint1.setColor(Color.WHITE);//設置畫筆paint1的顏色paint1.setStrokeWidth(5);//設置畫筆paint1的粗細度paint1.setStyle(Paint.Style.STROKE);//設置畫筆paint1的風格for (BNPoint point:pointArrayList){point.drawSelf(paint,paint1,canvas);//繪制所有觸控點}}public int[] getColor(){int[] result = new int[4];result[0] = (int)(Math.random()*255);result[1] = (int)(Math.random()*255);result[2] = (int)(Math.random()*255);result[3] = (int)(Math.random()*255);return result;}public void repaint(){SurfaceHolder holder = this.getHolder();Canvas canvas = holder.lockCanvas();try {synchronized (holder){onDraw(canvas);}}catch (Exception e){e.printStackTrace();}finally {if(canvas!=null){holder.unlockCanvasAndPost(canvas);}}}public boolean onTouchEvent(MotionEvent event){//int action = event.getAction();//單點觸控//int actionMasked = event.getAction()&MotionEvent.ACTION_MASK;//Android 1.6 和 Android 2.1中int actionMasked = event.getActionMasked();//獲得多點觸控檢測點int id = (event.getAction()&MotionEvent.ACTION_POINTER_ID_MASK) >>> MotionEvent.ACTION_POINTER_ID_SHIFT;//無符號右移獲取觸控點idswitch (actionMasked){case MotionEvent.ACTION_DOWN://第一個觸控點按下pointArrayList.add(id,new BNPoint(event.getX(id), event.getY(id),getColor(),id));//以id索引大小排序插入//順序對應ACTION_MOVE時event.getX(i)取出坐標的順序break;case MotionEvent.ACTION_POINTER_DOWN://第一個之后的觸控點按下pointArrayList.add(id,new BNPoint(event.getX(id),event.getY(id),getColor(),id));//觸控點按下時,將獲得(0 ~ 個數-1)中//可用的最小的id號,即后續按下的點可以獲得//先前已經抬起的觸控點的idbreak;case MotionEvent.ACTION_MOVE://主、輔點移動for (int i = 0;i<pointArrayList.size();i++){try {//float x =event.getX(pointArrayList.get(i).id);//可能會下標越界,因為觸控點的id不一定等于其下標float x = event.getX(i);float y = event.getY(i);pointArrayList.get(i).setLocation(x,y);}catch (Exception e){Log.d("MySurfaceView", "onTouchEvent: point.id=" + pointArrayList.get(i).id);e.printStackTrace();}}//pointArrayList.get(id).setLocation(event.getX(id),event.getY(id));//id=0,即如果沒有循環遍歷,則只會更新主控點break;case MotionEvent.ACTION_UP://最后一個點抬起pointArrayList.clear();break;case MotionEvent.ACTION_POINTER_UP://非最后一個點抬起pointArrayList.remove(id);//刪除一個觸控點后,該觸控點之后的點會向前移動,使得點的id不一定等于下標break;}repaint();return true;}public void surfaceCreated(SurfaceHolder holder){}public void surfaceChanged(SurfaceHolder holder,int arg1,int arg2,int arg3){this.repaint();}public void surfaceDestroyed(SurfaceHolder holder){}
}
(3)主活動類
主活動類主要是構建和加載視圖。
public class MainActivity extends AppCompatActivity {static float screenHeight;static float screenWidth;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//setContentView(R.layout.activity_main);ActionBar actionBar = getSupportActionBar();if(actionBar!=null){actionBar.hide();//隱藏標題欄}getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//豎屏DisplayMetrics metrics = new DisplayMetrics();getWindowManager().getDefaultDisplay().getMetrics(metrics);screenHeight = metrics.heightPixels;//屏幕大小screenWidth = metrics.widthPixels;MySurfaceView mySurfaceView = new MySurfaceView(this);setContentView(mySurfaceView);}
}
最終運行效果圖如下:
總結
以上是生活随笔為你收集整理的Android自定义View的多点触控的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【FinE】测度变换及Radon-Nic
- 下一篇: android sina oauth2.