本文原创,转载请注明:http://blog.csdn.net/cloudzfy1/article/details/6582707

Google 暑期大学生博客分享大赛 - 2011 Android 成长篇

如果您喜欢本文,请您投一下票:http://www.google.com/intl/zh-CN/daxue/blog/vote.html#tab2
谢谢。

最近需要做个Android的项目,需要使用多点触控的功能,上网找了很久,中文方面的资料相当少,英文方面也不多,经过自己的研究,加上对已知的一些资料的整理,下面为大家介绍一下Android多点触控程序的编写。

首先,我们准备好一张图片:

[置顶] Android多点触控揭秘_第1张图片

在Eclipse下新建一个Android工程(和一般Android工程一样),需要注意的是:Android的多点触控功能需要运行在Android 2.0版本以上。

[置顶] Android多点触控揭秘_第2张图片

完成后,我们需要将原先准备好的图片放进res/drawable文件夹下(注意,如果是Android2.2,请放在三个drawable文件夹下),如图所示:

[置顶] Android多点触控揭秘_第3张图片

该图片是为了给该多点触控的实例提供运行环境,实现图片的放大和缩小。

下面,我们来修改一下main.xml文件,如下所示:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    ><ImageView android:id="@+id/imageView"android:layout_width="fill_parent"android:layout_height="fill_parent"android:src="@drawable/img"android:scaleType="matrix" ></ImageView></LinearLayout>


对于让一张静态图片在Android面板上显示,我们可以采用下面的一句话:

ImageView imageView = (ImageView)findViewById(R.id.imageView);

通过设置Matrix,我们可以获得对ImageView的一些基本操作。

OK,啰嗦这么多,下面进入主题:

我们需要实现一个OnTouchListener的方法,来设置ImageView的侦听属性,该接口位于android.view.View.OnTouchListener。

实现onTouch(View view, MotionEvent event)的方法,就可以获取触屏的感应事件了。

在该事件中,有两个参数可以用来获取对触摸的控制,这两个参数分别为:MotionEvent.getAction()和MotionEvent.ACTION_MASK,前者用于对单点触控进行操作,后者用于对多点触控进行操作,相应地,我们可以通过Android Developers’ Reference看到,对于单点触控,我们由MotionEvent.getAction()可以得到以下几种事件:ACTION_DOWN、ACTION_UP,而对于多点触控,由MotionEvent.ACTION_MASK,我们可以得到:ACTION_POINTER_DOWN、ACTION_POINTER_UP,都是MotionEvent中的常量,可以直接调用。而有些常量则是单点和多点共用的,如:ACTION_MOVE,因此在按下时,我们必须标记单点与多点触控的区别。

下面我们来介绍一下缩放功能的实现,对于缩放,我们定义有两种手势,一种是双指拉伸式,一种是单指旋转式。

首先,双指拉伸式。

这是一种比较常规的图片缩放方式,实现起来也比较方便,我们可以很容易想到,在处理多点触控事件时,如果没有别的手势干扰,我们只需检测两指按下时和移动之后的位置关系即可,如果距离变大,则是放大图片;反之则是缩小图片。

主要代码如下:

if(mode == ZOOM){float newDistance;newDistance = (float)Math.sqrt((event.getX(0)-event.getX(1))*(event.getX(0)-event.getX(1))+(event.getY(0)-event.getY(1))*(event.getY(0)-event.getY(1)));if(newDistance > 10f) {matrix.set(savedMatrix);matrix.postScale(newDistance/oldDistance, newDistance/oldDistance, mid.x, mid.y);oldDistance = newDistance;savedMatrix.set(matrix);}}


然后,单指旋转式。

这是一种单指操作中比较流行的方式,然而实现起来并非特别方便。具体说来,我们可以定义顺时针转动为图片放大,逆时针转动为图片缩小。在没有其他干扰项的时候,我们可以通过捕获三次连续移动来得知手势顺时针还是逆时针。如下图所示,我们把前两次的位置作一个向量A,后两次位置作一个向量B,如果向量B比向量A大,则是逆时针;向量B比向量A小则是顺时针。当然,我们这里就要用到反三角函数,同时要注意2pi的角度问题哦~

[置顶] Android多点触控揭秘_第4张图片

注意:在处理同为单指操作或者同为多指操作的时候,要考虑不同行为之间的区别。

主要代码如下:

if (mode == MOVE){if(rotate == NONE) {savedMatrix.set(matrix);mid.set(event.getX(), event.getY());rotate = ROTATION;}else {matrix.set(savedMatrix);double a = Math.atan((mid.y-start.y)/(mid.x-start.x));double b = Math.atan((event.getY()-mid.y)/(event.getX()-mid.x));if ((b - a < Math.PI/2 && b - a > Math.PI / 18)||((b + Math.PI) % Math.PI - a < Math.PI/2 && (b + Math.PI) % Math.PI - a > Math.PI / 18)) {matrix.postScale((float)0.9, (float)0.9);}else if ((a - b < Math.PI / 2 && a - b > Math.PI / 18)||((a + Math.PI) % Math.PI - b < Math.PI/2 && (a + Math.PI) % Math.PI - b > Math.PI / 18)) {matrix.postScale((float)1.1, (float)1.1);}start.set(event.getX(), event.getY());rotate = NONE;}}


下面是实现的结果截图:

初始画面:

[置顶] Android多点触控揭秘_第5张图片

通过鼠标顺时针转动后的效果图:

[置顶] Android多点触控揭秘_第6张图片

通过鼠标逆时针转动后的效果图:

[置顶] Android多点触控揭秘_第7张图片

下面是代码的具体解析:

TouchActivity.java

package example.MultiTouch;import android.app.Activity;import android.graphics.Matrix;import android.graphics.PointF;import android.os.Bundle;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;import android.widget.ImageView;public class TouchActivity extends Activity {    private static final int NONE = 0;private static final int MOVE = 1;private static final int ZOOM = 2;private static final int ROTATION = 1;private int mode = NONE;private Matrix matrix = new Matrix();private Matrix savedMatrix = new Matrix();private PointF start = new PointF();private PointF mid = new PointF();private float s = 0;private float oldDistance;private int rotate = NONE;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                ImageView imageView = (ImageView)findViewById(R.id.imageView);        imageView.setOnTouchListener(new OnTouchListener()        {@Overridepublic boolean onTouch(View view, MotionEvent event) {ImageView imageView = (ImageView)view;switch (event.getAction()&MotionEvent.ACTION_MASK) {case MotionEvent.ACTION_DOWN:savedMatrix.set(matrix);start.set(event.getX(), event.getY());mode = MOVE;rotate = NONE;break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_POINTER_UP:mode = NONE;break;case MotionEvent.ACTION_POINTER_DOWN:oldDistance = (float)Math.sqrt((event.getX(0)-event.getX(1))*(event.getX(0)-event.getX(1))+(event.getY(0)-event.getY(1))*(event.getY(0)-event.getY(1)));if (oldDistance > 10f) {savedMatrix.set(matrix);mid.set((event.getX(0)+event.getX(1))/2, (event.getY(0)+event.getY(1))/2);mode = ZOOM;}case MotionEvent.ACTION_MOVE:if (mode == MOVE){if(rotate == NONE) {savedMatrix.set(matrix);mid.set(event.getX(), event.getY());rotate = ROTATION;}else {matrix.set(savedMatrix);double a = Math.atan((mid.y-start.y)/(mid.x-start.x));double b = Math.atan((event.getY()-mid.y)/(event.getX()-mid.x));if ((b - a < Math.PI/2 && b - a > Math.PI / 18)||((b + Math.PI) % Math.PI - a < Math.PI/2 && (b + Math.PI) % Math.PI - a > Math.PI / 18)) {matrix.postScale((float)0.9, (float)0.9);}else if ((a - b < Math.PI / 2 && a - b > Math.PI / 18)||((a + Math.PI) % Math.PI - b < Math.PI/2 && (a + Math.PI) % Math.PI - b > Math.PI / 18)) {matrix.postScale((float)1.1, (float)1.1);}start.set(event.getX(), event.getY());rotate = NONE;}}else if(mode == ZOOM){float newDistance;newDistance = (float)Math.sqrt((event.getX(0)-event.getX(1))*(event.getX(0)-event.getX(1))+(event.getY(0)-event.getY(1))*(event.getY(0)-event.getY(1)));if(newDistance > 10f) {matrix.set(savedMatrix);matrix.postScale(newDistance/oldDistance, newDistance/oldDistance, mid.x, mid.y);oldDistance = newDistance;savedMatrix.set(matrix);}}break;}imageView.setImageMatrix(matrix);return true;}                });    }}


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="example.MultiTouch"      android:versionCode="1"      android:versionName="1.0">    <uses-sdk android:minSdkVersion="8" />    <application android:icon="@drawable/icon" android:label="@string/app_name">        <activity android:name=".TouchActivity"                  android:label="@string/app_name">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>


更多相关文章

  1. ANDROID多点触控API接口的使用
  2. Android的Btimap处理大图片解决方法
  3. 如何实现手势缩放图片
  4. 直播软件源码Android 多个ImageView拖拽互换图片
  5. 【Android 界面效果6】Android 控件之ImageSwitcher图片切换器
  6. android图片上传
  7. Android Glide加载图片成圆形
  8. GifView控件,android显示gif图片
  9. Android 图片压缩实现过程代码

随机推荐

  1. 为Android(和其他移动平台)安装MoSync
  2. Android应用程序注冊广播接收器(registerR
  3. IDC:Android市场占有率仍未超越Symbian
  4. Android编程之manifest上遇到的错误
  5. Android(安卓)JNI开发入门之二(javah命令
  6. html5游戏移植到android并打包成apk,加广
  7. android中Invalidate和postInvalidate的
  8. Android使用Opencv图片处理 Mat与Bitmap
  9. Android系统的架构
  10. Android(安卓)adapter 数据适配器