閱讀803 返回首頁    go 阿裏雲 go 技術社區[雲棲]


關於android多點觸控

原文:https://www.cnblogs.com/tianjian/archive/2011/12/01/2270657.html

最近項目需要一個多點觸控縮放的功能。然後上網查了下資料 總結一下:

首先android sdk版本很重要,比如你在AndroidManifest.xml中指定android:minSdkVersion="4"  並且建工程的時候選的是android 2.2就表示你的應用兼容android1.6~android2.2

之間的版本。但是多點觸控的API在1.6~~2,1~~,2,2~~三個版本中都是不一樣的。比如android2.2中onTouchEvent(MotionEvent event) 這裏可以用event.getActionMasked()

表示用於多點觸控檢測點。但在1.6和2.1中並沒有event.getActionMasked()這個方法,查源碼後發現其實他就是吧event.getAction()& MotionEvent.ACTION_MASK封裝了一下。

對於這些小細節我們要特別注意,因為這關乎版本兼容問題,也許你在2.2的設備上運行沒什麼問題,但1.6或者2.1就會出個什麼問題之類的。所以對於1.6以後新增加的功能,要特別注意API

的使用。1.5就暫不考慮了。

接下來看代碼:

package laahaa.framework;
 
 
 
 import android.content.Context;
 import android.graphics.PointF;
 import android.util.AttributeSet;
 import android.util.FloatMath;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
 
 /**
  * 
  * 遊戲畫布
  */
 public class GameView2X extends GameView implements SurfaceHolder.Callback {
 
     private float oldDist;
     private PointF midPoint = new PointF();
     private boolean isZoom = false;
 
     public GameView2X(Context context, AttributeSet attrs) {
         super(context, attrs);
 
     }
 
     public boolean onTouchEvent(MotionEvent event) {
 
         switch (event.getAction() & MotionEvent.ACTION_MASK) {
         case MotionEvent.ACTION_DOWN:
             super.actionDown(event);
             break;
         case MotionEvent.ACTION_POINTER_UP:
             isZoom = false;
             break;
         /**
          * API原文是 A non-primary pointer has gone down.
          * 翻譯過來就是:非第一個點按下
 */
         case MotionEvent.ACTION_POINTER_DOWN:
             oldDist = spacing(event);
             midPoint(midPoint, event);
             isZoom = true;
             break;
         case MotionEvent.ACTION_MOVE:
             if (isZoom) {
                 float newDist = spacing(event);
                 /**
                  * 表示新的距離比兩個手指剛觸碰的距離大
                  * ( +10個像素用來延遲一下放大,不然稍微動一點像素,也放大,感覺也太快了。)
 */            
                 if (newDist + 10 > oldDist) {
                     super.getGameThread().getGameDraw()
                             .checkXY((int) midPoint.x, (int) midPoint.y);
                     super.getGameThread().getGameDraw().setIsZoom(true);
                 }
                 /**
                  * 表示新的距離比兩個手指剛觸碰的距離小
 */    
                 if (newDist + 10 < oldDist) {
                     super.getGameThread().getGameDraw().setIsZoom(false);
                     GameDraw.newX = 0;
                     GameDraw.newY = 0;
                 }
             }
             super.actionMove(event);
 
             break;
         }
 
         return true;
     }
 
     private float spacing(MotionEvent event) {
         float x = event.getX(0) - event.getX(1);
         float y = event.getY(0) - event.getY(1);
         return FloatMath.sqrt(x * x + y * y);
     }
 
     private void midPoint(PointF point, MotionEvent event) {
         float x = event.getX(0) + event.getX(1);
         float y = event.getY(0) + event.getY(1);
         point.set(x / 2, y / 2);
     }
 }

這裏要注意下GameView2X表示2.0以上的版本 他繼承於我自己寫的低版本的GameView。因為有很多重複代碼繼承是必須的。最後要注意下:獲取當前應用的SDK版本代碼為:

int sdkVersion=Integer.parseInt(Build.VERSION.SDK);

你需要在最開始初始化的時候運行它,寫入GameConfig中比較好,後麵單例調用就好了。或者不喜歡單例的直接static final 也行。然後再選擇gameview的時候 加個if判斷,

if(sdkVersion<Build.VERSION_CODES.ECLAIR)

{}

else

{}

好了,這裏的多點觸控放大比較簡單,其實可以根據前距離/後距離的比值來動態設置縮放。這隻是個簡單的例子。

ps:最近發現 onTouchEvent事件中的參數MotionEvent,它有一個getSize()方法。在一個點的時候,該方法永遠返回0,而在兩個觸電的時候,該方法則根據兩點相對位置變化而返回不同的值 







最後更新:2017-04-02 06:52:15

  上一篇:go Int32.Parse, Convert.ToInt32,Int32.TryParse三者的區別
  下一篇:go XmlToJson-xml對象轉換為Json對象類