最近项目需要一个多点触控缩放的功能。然后上网查了下资料 总结一下:
首先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就暂不考虑了。
接下来看代码:
1 package laahaa.framework; 2 3 4 5 import android.content.Context; 6 import android.graphics.PointF; 7 import android.util.AttributeSet; 8 import android.util.FloatMath; 9 import android.view.MotionEvent;10 import android.view.SurfaceHolder;11 12 /**13 * 14 * 游戏画布15 */16 public class GameView2X extends GameView implements SurfaceHolder.Callback {17 18 private float oldDist;19 private PointF midPoint = new PointF();20 private boolean isZoom = false;21 22 public GameView2X(Context context, AttributeSet attrs) {23 super(context, attrs);24 25 }26 27 public boolean onTouchEvent(MotionEvent event) {28 29 switch (event.getAction() & MotionEvent.ACTION_MASK) {30 case MotionEvent.ACTION_DOWN:31 super.actionDown(event);32 break;33 case MotionEvent.ACTION_POINTER_UP:34 isZoom = false;35 break;36 /**37 * API原文是 A non-primary pointer has gone down.38 * 翻译过来就是:非第一个点按下39 */40 case MotionEvent.ACTION_POINTER_DOWN:41 oldDist = spacing(event);42 midPoint(midPoint, event);43 isZoom = true;44 break;45 case MotionEvent.ACTION_MOVE:46 if (isZoom) {47 float newDist = spacing(event);48 /**49 * 表示新的距离比两个手指刚触碰的距离大50 * ( +10个像素用来延迟一下放大,不然稍微动一点像素,也放大,感觉也太快了。)51 */ 52 if (newDist + 10 > oldDist) {53 super.getGameThread().getGameDraw()54 .checkXY((int) midPoint.x, (int) midPoint.y);55 super.getGameThread().getGameDraw().setIsZoom(true);56 }57 /**58 * 表示新的距离比两个手指刚触碰的距离小59 */ 60 if (newDist + 10 < oldDist) {61 super.getGameThread().getGameDraw().setIsZoom(false);62 GameDraw.newX = 0;63 GameDraw.newY = 0;64 }65 }66 super.actionMove(event);67 68 break;69 }70 71 return true;72 }73 74 private float spacing(MotionEvent event) {75 float x = event.getX(0) - event.getX(1);76 float y = event.getY(0) - event.getY(1);77 return FloatMath.sqrt(x * x + y * y);78 }79 80 private void midPoint(PointF point, MotionEvent event) {81 float x = event.getX(0) + event.getX(1);82 float y = event.getY(0) + event.getY(1);83 point.set(x / 2, y / 2);84 }85 }
这里要注意下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,而在两个触电的时候,该方法则根据两点相对位置变化而返回不同的值