申明:

参考:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2013/0226/914.html

下面实现如何通过应用层支持多点触控操作,对于常规的控件触控操实现onTouchEvent()方法来处理。同时对onTouchEvent方法的参数MotionEvent进行一些了解。


正文:

下面会用两个应用示例来初步学习一下Android中的多点触控。


示例一(DemoMultiTouch-Canvas):

核心技术介绍

本示例是在SurfaceView中利用Canvas来展示用户的多点触控,不过核心技术还是一个常见的方法:onTouchEvent(MotionEvent event)

MotionEvent有以下几个方法需要大家注意一下,不过了是一些常见的方法,如果你onTouchEvent使用得多的话。

event.getAction() // 获取触控动作比如ACTION_DOWN
event.getPointerCount(); // 获取触控点的数量,比如2则可能是两个手指同时按压屏幕
event.getPointerId(nID); // 对于每个触控的点的细节,我们可以通过一个循环执行getPointerId方法获取索引
event.getX(nID); // 获取第nID个触控点的x位置
event.getY(nID); // 获取第nID个点触控的y位置
event.getPressure(nID); // LCD可以感应出用户的手指压力,当然具体的级别由驱动和物理硬件决定的
event.getDownTime() // 按下开始时间
event.getEventTime() // 事件结束时间
event.getEventTime()-event.getDownTime()); // 总共按下时花费时间


代码展示:

public class MTView extends SurfaceView implements SurfaceHolder.Callback {private static final int MAX_TOUCHPOINTS = 10;private static final String START_TEXT = "请随便触摸屏幕进行测试";private Paint textPaint = new Paint();private Paint touchPaints[] = new Paint[MAX_TOUCHPOINTS];private int colors[] = new int[MAX_TOUCHPOINTS];private int width, height;private float scale = 1.0f;public MTView(Context context) {super(context);SurfaceHolder holder = getHolder();holder.addCallback(this);setFocusable(true); // 确保我们的View能获得输入焦点setFocusableInTouchMode(true); // 确保能接收到触屏事件init();}private void init() {// 初始化10个不同颜色的画笔textPaint.setColor(Color.WHITE);colors[0] = Color.BLUE;colors[1] = Color.RED;colors[2] = Color.GREEN;colors[3] = Color.YELLOW;colors[4] = Color.CYAN;colors[5] = Color.MAGENTA;colors[6] = Color.DKGRAY;colors[7] = Color.WHITE;colors[8] = Color.LTGRAY;colors[9] = Color.GRAY;for (int i = 0; i < MAX_TOUCHPOINTS; i++) {touchPaints[i] = new Paint();touchPaints[i].setColor(colors[i]);}}/** * 处理触屏事件 */@Overridepublic boolean onTouchEvent(MotionEvent event) {// 获得屏幕触点数量int pointerCount = event.getPointerCount();if (pointerCount > MAX_TOUCHPOINTS) {pointerCount = MAX_TOUCHPOINTS;}// 锁定Canvas,开始进行相应的界面处理Canvas c = getHolder().lockCanvas();if (c != null) {c.drawColor(Color.BLACK);if (event.getAction() == MotionEvent.ACTION_UP) {// 当手离开屏幕时,清屏} else {// 在每一个触点上绘制一个十字和坐标信息for (int i = 0; i < pointerCount; i++) {int id = event.getPointerId(i);int x = (int) event.getX(i);int y = (int) event.getY(i);drawCrosshairsAndText(x, y, touchPaints[id], i, id, c);}// 在每一个触点上绘制一个圆for (int i = 0; i < pointerCount; i++) {int id = event.getPointerId(i);int x = (int) event.getX(i);int y = (int) event.getY(i);drawCircle(x, y, touchPaints[id], c);}}// 画完后,unlockgetHolder().unlockCanvasAndPost(c);}return true;}/** * 画十字及坐标信息 *  * @param x * @param y * @param paint * @param ptr * @param id * @param c */private void drawCrosshairsAndText(int x, int y, Paint paint, int ptr,int id, Canvas c) {c.drawLine(0, y, width, y, paint);c.drawLine(x, 0, x, height, paint);int textY = (int) ((15 + 20 * ptr) * scale);c.drawText("x" + ptr + "=" + x, 10 * scale, textY, textPaint);c.drawText("y" + ptr + "=" + y, 70 * scale, textY, textPaint);c.drawText("id" + ptr + "=" + id, width - 55 * scale, textY, textPaint);}/** * 画圆 *  * @param x * @param y * @param paint * @param c */private void drawCircle(int x, int y, Paint paint, Canvas c) {c.drawCircle(x, y, 40 * scale, paint);}/** * 进入程序时背景画成黑色,然后把START_TEXT写到屏幕 */public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {this.width = width;this.height = height;if (width > height) {this.scale = width / 480f;} else {this.scale = height / 480f;}textPaint.setTextSize(14 * scale);Canvas c = getHolder().lockCanvas();if (c != null) {c.drawColor(Color.BLACK);float tWidth = textPaint.measureText(START_TEXT);c.drawText(START_TEXT, width / 2 - tWidth / 2, height / 2, textPaint);getHolder().unlockCanvasAndPost(c);}}public void surfaceCreated(SurfaceHolder holder) {}public void surfaceDestroyed(SurfaceHolder holder) {}}


使用上也是so easy:

setContentView(new MTView(this));


运行效果图:

Android多点触控MultiTouch浅析_第1张图片


示例二(DemoMultiTouch-ImageView):

通过多点触屏放大或缩小图像 beforeLenght用来保存前一时间两点之间的距离 afterLenght用来保存当前时间两点之间的距离

public void scaleWithFinger(MotionEvent event) {float moveX = event.getX(1) - event.getX(0);float moveY = event.getY(1) - event.getY(0);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:beforeLenght = (float) Math.sqrt((moveX * moveX)+ (moveY * moveY));break;case MotionEvent.ACTION_MOVE:// 得到两个点之间的长度afterLenght = (float) Math.sqrt((moveX * moveX)+ (moveY * moveY));float gapLenght = afterLenght - beforeLenght;if (gapLenght == 0) {break;}// 如果当前时间两点距离大于前一时间两点距离,则传0,否则传1if (gapLenght > 0) {this.setScale(scale, 0);} else {this.setScale(scale, 1);}beforeLenght = afterLenght;break;}}}


让图片跟随手指触屏的位置移动 beforeX、Y是用来保存前一位置的坐标 afterX、Y是用来保存当前位置的坐标。它们的差值就是ImageView各坐标的增加或减少值。

public void moveWithFinger(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:beforeX = event.getX();beforeY = event.getY();break;case MotionEvent.ACTION_MOVE:afterX = event.getX();afterY = event.getY();this.setLocation((int) (afterX - beforeX),(int) (afterY - beforeY));beforeX = afterX;beforeY = afterY;break;case MotionEvent.ACTION_UP:break;}}


用来放大缩小ImageView 因为图片是填充ImageView的,所以也就有放大缩小图片的效果 flag为0是放大图片,为1是缩小图片

private void setScale(float temp, int flag) {if (flag == 0) {this.setFrame(this.getLeft() - (int) (temp * this.getWidth()),this.getTop() - (int) (temp * this.getHeight()),this.getRight() + (int) (temp * this.getWidth()),this.getBottom() + (int) (temp * this.getHeight()));} else {this.setFrame(this.getLeft() + (int) (temp * this.getWidth()),this.getTop() + (int) (temp * this.getHeight()),this.getRight() - (int) (temp * this.getWidth()),this.getBottom() - (int) (temp * this.getHeight()));}}


onTouchEvent事件则如下:

public boolean onTouchEvent(MotionEvent event) {if (inView(imageView, event)) {if (event.getPointerCount() == 2) {imageView.scaleWithFinger(event);} else if (event.getPointerCount() == 1) {imageView.moveWithFinger(event);}}return true;}

源码下载:

http://download.csdn.net/detail/u013761665/8719349

更多相关文章

  1. Android 时间倒计时
  2. Android应用程序设置系统时间的方法
  3. Android ApiDemos示例解析(159):Views->Layouts->TableLayout->0
  4. Android中如何修改系统时间(应用程序获得系统权限)
  5. Android(安卓)时间戳和日期之间的转化
  6. 微信小程序时间转换
  7. Android 如何提前知道fling velocity的距离、时间 根据滑动距离
  8. Android SQLite详解及示例代码

随机推荐

  1. android知识点
  2. android JNI 学习笔记1
  3. Android(安卓)Studio单元测试
  4. ui布局参数设置
  5. Android(安卓)增加对鼠标的支持
  6. Android(安卓)内核开发初步
  7. Hello Android
  8. android N多窗口和画中画属性
  9. JavaScript与Android之间的交互
  10. Android(安卓)为联系人添加图片