说三道四技术文摘-感悟人生的经典句子
说三道四 > 文档快照

手势识别兼容Android 1.x和2.x的代码

HTML文档下载 WORD文档下载 PDF文档下载
手势识别兼容Android 1.x和2.x的代码

作者:Android开发网


   由于Android 2.x开始很多API变动比较大新增了一些比如多点触控的支持,对于屏幕触控手势识别中我们需要考虑更多的实现方法,下面是一段兼容Android 1.x和2.x的代码,可以让我们的程序兼容几乎99%的Android手机。

  一、首先新建一个抽象类判断SDK版本问题

 public abstract class VersionedGestureDetector {
    private static final String TAG = "VersionedGestureDetector";

    OnGestureListener mListener;

    public static VersionedGestureDetector newInstance(Context context,
            OnGestureListener listener) {  //设计实例化构造方法,这里Android123提示大家目前有3种API的实现方法,我们需要逐一考虑最优的解决方法,以满足高平台更多的功能实现。

        final int sdkVersion = Integer.parseInt(Build.VERSION.SDK); //使用android.os.Build判断API Level,但需要将字符串转换为整形
        VersionedGestureDetector detector = null;
        if (sdkVersion < Build.VERSION_CODES.ECLAIR) { //如果版本小于2.0则使用1.5版本的API,可以兼容1.5和1.6
            detector = new CupcakeDetector();
        } else if (sdkVersion < Build.VERSION_CODES.FROYO) { //如果版本小于2.1则使用2.0版本的API,可以兼容2.0,2.0.1和2.1这三个版本
            detector = new EclairDetector();
        } else {  //否则使用2.2开始的新的触控API

            detector = new FroyoDetector(context);
        }

        Log.d(TAG, "Created new " + detector.getClass()); //判断最终选择的到底是哪个版本的类
        detector.mListener = listener;

        return detector;
    }

    public abstract boolean onTouchEvent(MotionEvent ev); //我们需要根据版本决定onTouchEvent的实现

    public interface OnGestureListener { //手势判断接口主要是实现两个方法
        public void onDrag(float dx, float dy);  //拖拽
        public void onScale(float scaleFactor); //缩放
    }

    private static class CupcakeDetector extends VersionedGestureDetector { //针对Android 1.5和1.6设计的兼容方式
        float mLastTouchX;
        float mLastTouchY;

        float getActiveX(MotionEvent ev) { //获得当前X坐标
            return ev.getX();
        }

        float getActiveY(MotionEvent ev) { //获得当前Y坐标
            return ev.getY();
        }

        boolean shouldDrag() { //是否是拖拽中或者说移动中
            return true;
        }

        @Override
        public boolean onTouchEvent(MotionEvent ev) { //重写onTouchEvent方法
            switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN: {  //向下
                mLastTouchX = getActiveX(ev);
                mLastTouchY = getActiveY(ev);
                break;
            }
            case MotionEvent.ACTION_MOVE: { //Android开发网提醒大家,由于1.x时代的API比较简单,很多手势没有封装,我们只能从ACTION_MOVE中根据坐标变化判断手势样式
                final float x = getActiveX(ev);
                final float y = getActiveY(ev);

                if (shouldDrag()) {
                    mListener.onDrag(x - mLastTouchX, y - mLastTouchY); //处理拖拽移动
                }

                mLastTouchX = x;
                mLastTouchY = y;
                break;
            }
            }
            return true;
        }
    }

    private static class EclairDetector extends CupcakeDetector { //这个是针对Android 2.0,2.0.1和2.1提供的解决方法,可以看到有很多多点触控相关API出现
        private static final int INVALID_POINTER_ID = -1;
        private int mActivePointerId = INVALID_POINTER_ID;
        private int mActivePointerIndex = 0;

        @Override
        float getActiveX(MotionEvent ev) {
            return ev.getX(mActivePointerIndex);
        }

        @Override
        float getActiveY(MotionEvent ev) {
            return ev.getY(mActivePointerIndex);
        }

        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            final int action = ev.getAction();
            switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                mActivePointerId = ev.getPointerId(0);
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                mActivePointerId = INVALID_POINTER_ID;
                break;
            case MotionEvent.ACTION_POINTER_UP: //有个点松开
                final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
                        >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
                final int pointerId = ev.getPointerId(pointerIndex); //获取第几个点
                if (pointerId == mActivePointerId) {
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    mActivePointerId = ev.getPointerId(newPointerIndex);
                    mLastTouchX = ev.getX(newPointerIndex); //处理第newPointerIndex个点的x位置
                    mLastTouchY = ev.getY(newPointerIndex);
                }
                break;
            }

            mActivePointerIndex = ev.findPointerIndex(mActivePointerId);
            return super.onTouchEvent(ev);
        }
    }

    private static class FroyoDetector extends EclairDetector { //从Android 2.2开始可以很好的处理多点触控的缩放问题
        private ScaleGestureDetector mDetector;

        public FroyoDetector(Context context) {
            mDetector = new ScaleGestureDetector(context,
                    new ScaleGestureDetector.SimpleOnScaleGestureListener() {
                @Override public boolean onScale(ScaleGestureDetector detector) {
                    mListener.onScale(detector.getScaleFactor()); //根据 ScaleGestureDetector.SimpleOnScaleGestureListener这个系统类处理缩放情况通过onScale方法
                    return true;
                }
            });
        }

        @Override
        boolean shouldDrag() {
            return !mDetector.isInProgress();
        }

        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            mDetector.onTouchEvent(ev);
            return super.onTouchEvent(ev);
        }
    }
}

 有关调用方法,我们可以自定义一个View,取名为TouchExampleView类,这里来处理触控相关的问题

public class TouchExampleView extends View {
    private Drawable mIcon; //我们以一个图片为参照物,根据手势控制
    private float mPosX;
    private float mPosY;

    private VersionedGestureDetector mDetector;
    private float mScaleFactor = 1.f; //原始缩放比例为1.0

    public TouchExampleView(Context context) {
        this(context, null, 0);
    }

    public TouchExampleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TouchExampleView(Context context, AttributeSet attrs, int defStyle) { //实现我们自定义View的构造
        super(context, attrs, defStyle);
        mIcon = context.getResources().getDrawable(R.drawable.icon);
        mIcon.setBounds(0, 0, mIcon.getIntrinsicWidth(), mIcon.getIntrinsicHeight());

        mDetector = VersionedGestureDetector.newInstance(context, new GestureCallback()); //实例化刚才的版本自适应手势控制类
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) { //重写onTouchEvent方法,使用VersionedGestureDetector类得出的数据。
        mDetector.onTouchEvent(ev);
        return true;
    }

    @Override
    public void onDraw(Canvas canvas) { //处理自定义View绘制方法
        super.onDraw(canvas);

        canvas.save();
        canvas.translate(mPosX, mPosY); //进行平移操作,根据mPosX和mPosY坐标
        canvas.scale(mScaleFactor, mScaleFactor); //进行缩放操作,参数就是刚才定义的float类型的缩放比例
        mIcon.draw(canvas); //直接绘制图片变化到画布中
        canvas.restore();
    }

    private class GestureCallback implements VersionedGestureDetector.OnGestureListener {
        public void onDrag(float dx, float dy) { //这里Android123提示大家在2.2中这个回调方法将可以支持拖拽的坐标处理
            mPosX += dx;
            mPosY += dy;
            invalidate();
        }

        public void onScale(float scaleFactor) {
            mScaleFactor *= scaleFactor; //缩放控制

            mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f)); //限制最小缩放比例为1.0最大为5.0倍数

            invalidate();
        }
    }
}

 有关调用我们的自定义的TouchExampleView可以在Activity的onCreate方法中加入以下代码,

     TouchExampleView view = new TouchExampleView(this);
     view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
      ViewGroup.LayoutParams.MATCH_PARENT));

     setContentView(view);  //替换掉原始的res.layout.main

最后Android123需要给大家说明的是使用本例子,直接使用Android 2.2的SDK创建工程,即API Level为8,发布时在androidmanifest.xml中加入uses-sdk android:minSdkVersion="3" android:targetSdkVersion="8"这句可以兼容从Android 1.5到2.2的版本,有关2.3中新增的一个可以处理5个或5个以上的多点触控增强类Android开发网将在以后的时间中介绍。

揭秘Instagram Hyperlapse背后的技术 【CTO俱乐部在线教育研讨会】用互联网技术深入创新教育产品 降低门槛!Hybrid应用开发框架LigerMobile 下一代IT革命:微服务器和雾计算 使用Mongo Connector和Elasticsearch实现模糊匹配 时隔8个月,物联网联盟AllSeen如今怎样? 《近匠》简网:开发零门槛 快速建原生App MDCC免费展位申请超预期 大会内容初曝光 在服务器与交换机定制之后,谷歌着手量子计算机CPU设计 电信天翼开放平台鲍占斌:优质能力 分成比例高 艾格拉斯副总裁王晓波:手游定价如何设计 Xcode 6 Beta 7发布:语法定、内库改,Swift何时完善? 干货来袭:由22个联邦机构分享的6482个数据集 Phablet出货量今年将超移动PC,明年再超平板 如何提高Web服务端并发效率的异步编程技术? 改改改!让应用通过审核出人头地的10个方法 正益无线CEO王国春:AppCan如何获得50万开发者青睐 在收购Xtreme Labs之后,Pivotal推出PaaS移动服务 .NET开发者必备的11款免费工具 .NET开发不可错过的25款高效工具 Docker最佳实践!尽在2014 Container技术大会 pflua:用Lua编写的高性能网络包过滤工具箱 掌上明珠张磊:如何设计手游付费体系 云游科技何千军:游戏开发和后端逻辑经验 《近匠》Highway1:孵化,不只是简单的帮助 嘉宾来了 MDCC 2014首批演讲嘉宾名单公布 前雅虎CTO:Hadoop扩展过程中的7个危险信号 【云先锋】星环TDH:性能大幅领先于开源Hadoop2的技术架构赏析 一周消息树:我想创业,但不懂技术怎么办? GitHub迁移数据库,借助MySQL大行其道! 实例亲授:教你如何创建AR应用 哪里有windowsXP下载? 送我能给的最大分,请教很小的问题,中高手进 聊天请进(thinkingdog) 大家来谈谈 IBM都有些什么认证???什么认证现在比较吃香???谢谢!!! 打印数窗问题求助! 如何使用UrlDownloadtoFile下载文件使用进度条? 如何用在两次用getTime()中得到两个不同的时间。 一个类似于牛角尖的问题(多余的CONST),不能忽视,请各位高手详细说明!!谢谢! 怎样读写注册表,每次都不成功,气死我也~! 各位救命啊,用 TClientDataSet.Load XML 的问题。。。。 娃呀呀,pb8怎么这么难安装?jaguar组建就用了5分钟,regester window又用了10分钟,重启动后,还没完,偶不敢装了,把碟退了出来,大家是不是也这样?//牛虻 请教高手一个ado的问题. 请问一个TWebBrowser的问题 请问:系统崩溃后,找不到BOOT,系统告诉:DOS基本分区为格式化?无法引导启动! 在VB.NET的tabcontrol上放置AxMSFlexGrid控件问题,急 java3D 现在大家是用Oracle 8还是 Oracle 9??? C++问题求助! 请教一个错误的原因. 各位大侠请问Jeffrey Richter的windows核心程序设计是不是就是andvanced windows程序设计的第四版 SCJP里的那些什么300-020,020是什么意思啊? 请问一个关于document.write()方法的问题。急啊! 初学者,欢迎灌水。 Delphi6的Bug?不兼容? 为什么我用GetProfileString()却总是得不到结果 sos 请教各位大侠一个问题 delphi6中的installShield 请介绍接收端CRC校验传输内容是否正确的方法,资料或代码。谢谢! 各位大侠请问Jeffrey Richter的windows核心程序设计是不是就是andvanced windows程序设计的第四版? 谁会做软件狗?有钱赚了!!! 为什么我用QuickRep作的报表只能显示一条记录,而且columnHeaderBand上内容也显示不出来 请问在税务局开发数据库的同行么?? 大家好各位大侠请问Jeffrey Richter的windows核心程序设计是不是就是andvanced windows程序设计的第四版? 谁做过软件狗,马上来拿钱!!! 江苏省的成绩什么时候可以出来啊,我是徐州的 shockwaveflash没有hwnd,怎么办? chechy(chechy) 你在吗? 一个关于用excel做的日报的问题 谁会做软件狗,马上来拿钱!!! 给你下跪了,给你磕头了,给你鞠躬了。很简单的问题。谢谢 那位大哥能告诉我在VC中我要创建类的话应该做哪些工作步骤(要详细的,呵呵) 紧急求救,asp连接mysql问题 在使用twebbrowser的时候,怎样制止网页的自动刷新和跳转? vc编译器错了怎么办???突然死机,然后就不好好干了!!谢谢 ?如何将二进制的 值写如注册表? Delphi紧急求助! 我想问的是,返回的 ResultSet 中的某个字段(int 型),如何放到一个 int[]数组里去。因为 ResultSet 不知道怎样取 size,我又不想用 vector, ResultSet的getArray()方法也是莫名其妙。 c盘格式化后,怎样找到linux系统? 有意思 过来研究一下!!!!insert 的!!!!难道 25 不是 long integer 吗 我的程序debug版,一直调试好好的,我rebuid all 一下就出错了,错误如下:怎么回事? 位图问题? 把1.5长的竹竿直立在地面,测得竹竿的影子长是1.2米,同时量得一根旗杆的影子是这竹竿影子的6倍还多80厘米求旗杆的长. 肯德基的炸鸡配方全球只有俩人知道?那为什么全球各地的KFC的炸鸡基本是一个味?我没问它是不是垃圾食品,我只想知道,一方面,配方高度保密,另一方面,遍布全球的连锁店却出售同一口味的炸 想了解一下各种气候类型的特点,这不是快要地理生物会考了嘛.认真学习一下. 小明把2.5米的竹竿直立在地上,量得它的影子长度是1.5米.如果同一时间、同一地点量得一根电线的影子长度4.8米.这根电线杆高多少米?用比例解。 在空地上立一根竿子,让竿子被太阳照射,当一天中竿子的最短时,竿子的影子朝什么方向猪头滚从东.南.西.北和东南.西南.东北.西北中选 沼气池建好后,每天会产1万方的沼气提纯成5000方天然气压缩成20兆帕的一个成套设备需要投资多少钱啊?运行费用每立方需要多少成本?(沼气池是无动力运行的,每天自动产1万立方沼气) 紫铜管钎焊焊缝能用射线检测吗 为什么西西伯利亚平原多沼泽 一天中,阳光下直立物体影子长短有什么变化?爱你? “春天的花开,秋天的风以及冬天的落日”是哪首歌里的词 根据规范的方法,超声波测砼裂缝的深度最小值是多少?为什么? 看云识天气写了几种云,分别对应什么天气 从一天当中阳光下的物体的影子的变化发现什么 混凝土的碳化深度怎么测定 请问以下几种云 是什么云 代表着什么样的天气状况隔着窗户拍的 效果不太好 有污点. 你的家在——,一天当中阳光下的物体的影子是怎样变化的?5年级《寒假之友》4页 急!早晨。上午。傍晚。中午的影子。 通过观察你发现了什么? 当声波在混凝土内传播穿过裂缝时,在裂缝端点处产生衍射,其衍射角与裂缝深度具有一定的几何关系.BJCS-1型混凝土裂缝测深仪正是依据衍射角与裂缝深度的几何关系,自动计算实现裂缝深度的 表示天气的或云的成语有哪些 二氧化碳气体保护焊能不能焊接压力容器 二氧化碳气体保护焊能不能焊接压力容器我是一名焊工,制造压力容器采用二氧化碳气体保护焊焊接A、B类焊缝成形可以,X光照射也可以,就是厂里没有 A、汶川大地震 B、我国东南地区的超强台风 C、西伯利亚地区大片沼泽的的形成 D、全球范围内的大气污染日益严重 请问上面四个选项中哪一个是由于人类活动对地表形态的破坏而造成的恶 求表示天气的或云的成语 CO2焊为什么不能焊接压力容器 一个太阳,竹竿,竹竿的影子是什么成语 天上云代表什么天气?云的形态各式各样,那每个形状都代表什么天气? 焊接压力容器是手工电弧焊好还是二氧化碳气体保护焊焊接好? 垂直竖立在地面上的竹竿,阳光照射下竹竿影子一样长,太阳与地面夹角是多少度 混凝土裂缝怎么处理 压力容器主体焊缝可以用二氧化碳保护焊吗 阳光下,影子的位置和太阳的位置有什么关系?影子的变化和太阳位置的变化以及时间的变化又有什么关系? 混凝土裂缝的产生混凝土在下列情况下,均能导致其产生裂缝,试解释裂缝产生的原因,并指出主要防止措施.水泥水化热大;水泥安定性不良;大气温度变化较大;碱一骨料反应;混凝土碳化; 在同一时间,同一地方的阳光照射下,物体的影子长度和物体高度成什么比例 kfc的菜单 法国的气候类型 一年中每天正午阳光下同一物体影子的长度有什么变化 关于肯德基华莱士,这些仿肯德基的餐厅,点餐都是在菜单上点的,为什么肯德基这些规范的餐厅,点餐反而要在后面的玻璃上点,菜单上的只有套餐却没有单点的,比如一个汉堡包,而且肯德基的套 法国气候类型 铅笔影子的长度约是?身体影子的长度约是?是在阳光下测量,铅笔就是一般的铅笔,人是156左右高矮的人, 肯德基的全家桶.2014年的新春全家桶有什么(名字)、内容、价格和时间. 法国有什么气候类型?急 一天中铅笔的影子的长度是怎样变化的? 西西伯利亚平原与东欧平原同是平原为什么气候差别如此大 法国的气候具有什么特点? 紧急!谁能提供标准GB/T3274-2007里的(普通轧制精度)数值.普通钢板的厚度偏差范围是多少? 东欧平原和西西伯利亚平原的地理环境区别 秋天的落叶,散文开头,落叶的描写我只要一小段开头,很有意境的那种,不要敷衍, GB/T3274-2007 数值Q235B主要问尺寸标准 东欧平原和西西伯利亚平原哪个大?还有为什么在世界地形图上看东欧平原和西西伯利亚都比亚马孙平原大?最好简洁一点! 谁能写《秋天的落叶》作文(纯属自写,不能和其他重复). 钢板选N类,A类,B类,C类的原则是什么?GB/T709-2006中的钢材厚度偏差分类. 中西伯利亚平原,西西伯利亚高原为什么要以西伯利亚命名 世界上最深的地震裂缝有多深?哪些地震裂缝超深? 各位老大,请问GB/T3274与GB/T709都是钢板标准,他们有什么区别? 为什么 肯德基配方 地震时造成大地出现裂缝然后那个裂缝是怎样补救的不过我还有一点不明白,就是沙的空隙会有很多'而地震时裂开的缝隙应该是土'然而给他灌沙他起不了很大的坚固性啊. GB 10055-2007这个标准谁有啊? 我想知道肯德基的配方 什么是地震深度? 太阳光斜照地面,光线与水平面所成的角为b,长为l的竹竿与地面所成的角为a,当a为多少时,竹竿的影子最长 KFC的热橙汁的配料是什么?为什么我用雀巢的橙汁加方糖却调配不出kfc里的那种味道.橙汁粉放少了,觉得味道不浓,橙汁粉放多,又觉得味道很酸,加了糖或者方糖,又感觉太甜?到底kfc里是怎么配 地震时产生地面裂缝 裂缝下面是什么了?如题 为什么人掉下去之后会怎么样呢?
备案号:鲁ICP备13029499号-2 说三道四 www.s3d4.cn