2019独角兽企业重金招聘Python工程师标准>>>

很多时候,利用触摸屏的Fling、Scroll等Gesture(手势)操作来操作会使得应用程序的用户体验大大提升,比如用Scroll手势在 浏览器中滚屏,用Fling在阅读器中翻页等。在Android系统中,手势的识别是通过 GestureDetector.OnGestureListener接口来实现的,不过William翻遍了Android的官方文档也没有找到一个相 关的例子,API Demo中的TouchPaint也仅仅是提到了onTouch事件的处理,没有涉及到手势。Android Developer讨论组里也有不少人有和我类似的问题,结合他们提到的方法和我所做的实验,我将给大家简单讲述一下Android中手势识别的实现。  
       我们先来明确一些概念,首先,Android的事件处理机制是基于Listener(监听器)来实现的,比我们今天所说的触摸屏相关的事件,就是通 过onTouchListener。其次,所有View的子类都可以通过setOnTouchListener()、 setOnKeyListener()等方法来添加对某一类事件的监听器。第三,Listener一般会以Interface(接口)的方式来提供,其中 包含一个或多个abstract(抽象)方法,我们需要实现这些方法来完成onTouch()、onKey()等等的操作。这样,当我们给某个view设 置了事件Listener,并实现了其中的抽象方法以后,程序便可以在特定的事件被dispatch到该view的时候,通过callbakc函数给予适 当的响应。  
看一个简单的例子,就用最简单的TextView来说明(事实上和ADT中生成的skeleton没有什么区别)。 
Java代码

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);    setContentView(R.layout.main);    // init TextView TextView tv = (TextView) findViewById(R.id.page);    // set OnTouchListener on TextView tv.setOnTouchListener(this);    // show some text tv.setText(R.string.text);
}    @Override
public boolean onTouch(View v, MotionEvent event) {    Toast.makeText(this, "onTouch", Toast.LENGTH_SHORT).show();return false;
}

我们给TextView的实例tv设定了一个onTouchListener,因为GestureTest类实现了OnTouchListener 接口,所以简单的给一个this作为参数即可。onTouch方法则是实现了OnTouchListener中的抽象方法,我们只要在这里添加逻辑代码即 可在用户触摸屏幕时做出响应,就像我们这里所做的——打出一个提示信息。 
这里,我们可以通过MotionEvent的getAction()方法来获取Touch事件的类型,包括 ACTION_DOWN, ACTION_MOVE, ACTION_UP, 和ACTION_CANCEL。ACTION_DOWN是指按下触摸屏,ACTION_MOVE是指按下触摸屏后移动受力点,ACTION_UP则是指松 开触摸屏,ACTION_CANCEL不会由用户直接触发(所以不在今天的讨论范围,请参考ViewGroup.onInterceptTouchEvent(MotionEvent))。借助对于用户不同操作的判断,结合getRawX()、getRawY()、getX()和getY()等方法来获取坐标后,我们可以实现诸如拖动某一个按钮,拖动滚动条等功能。待机可以看看MotionEvent类的文档,另外也可以看考TouchPaint例子。  
回到今天所要说的重点,当我们捕捉到Touch操作的时候,如何识别出用户的Gesture?这里我们需要GestureDetector.OnGestureListener接口的帮助,于是我们的GestureTest类就变成了这个样子。 
Java代码

public class GestureTest extends Activity implements OnTouchListener,    OnGestureListener {
....
}

随后,在onTouch()方法中,我们调用GestureDetector的onTouchEvent()方法,将捕捉到的MotionEvent交给 GestureDetector 来分析是否有合适的callback函数来处理用户的手势。 
Java代码

@Override
public boolean onTouch(View v, MotionEvent event) {    // OnGestureListener will analyzes the given motion eventreturn mGestureDetector.onTouchEvent(event);
}

接下来,我们实现了以下6个抽象方法,其中最有用的当然是onFling()、onScroll()和onLongPress()了。我已经把每一个方法代表的手势的意思写在了注释里,大家看一下就明白了。 
// 用户轻触触摸屏,由1个MotionEvent ACTION_DOWN触发Java代码

@Override
public boolean onDown(MotionEvent e) {    // TODO Auto-generated method stub Toast.makeText(this, "onDown", Toast.LENGTH_SHORT).show();    return false;
}    // 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
// 注意和onDown()的区别,强调的是没有松开或者拖动的状态 @Override
public void onShowPress(MotionEvent e) {    // TODO Auto-generated method stub
}

用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发

@Overridepublic boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub return false;
}

用户按下触摸屏、快速移动后松开,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE, 1个ACTION_UP触发

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,    float velocityY) {    // TODO Auto-generated method stub return false;
}    // 用户长按触摸屏,由多个MotionEvent ACTION_DOWN触发
@Override
public void onLongPress(MotionEvent e) {    // TODO Auto-generated method stub
}    // 用户按下触摸屏,并拖动,由1个MotionEvent ACTION_DOWN, 多个ACTION_MOVE触发
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
// TODO Auto-generated method stub return false;
}

我们来试着做一个onFling()事件的处理吧,onFling()方法中每一个参数的意义我写在注释中了,需要注意的是Fling事件的处理代 码中,除了第一个触发Fling的ACTION_DOWN和最后一个ACTION_MOVE中包含的坐标等信息外,我们还可以根据用户在X轴或者Y轴上的 移动速度作为条件。比如下面的代码中我们就在用户移动超过100个像素,且X轴上每秒的移动速度大于200像素时才进行处理。

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {    // 参数解释:
// e1:第1个ACTION_DOWN MotionEvent
// e2:最后一个ACTION_MOVE MotionEvent
// velocityX:X轴上的移动速度,像素/秒
// velocityY:Y轴上的移动速度,像素/秒
// 触发条件 :
// X轴的坐标位移大于FLING_MIN_DISTANCE,且移动速度大于FLING_MIN_VELOCITY个像素/秒
if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE    && Math.abs(velocityX) > FLING_MIN_VELOCITY) {    // Fling left Toast.makeText(this, "Fling Left", Toast.LENGTH_SHORT).show();    } else
if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE    && Math.abs(velocityX) > FLING_MIN_VELOCITY) {    // Fling right Toast.makeText(this, "Fling Right", Toast.LENGTH_SHORT).show();
}    return false;
}

问题是,这个时候如果我们尝试去运行程序,你会发现我们根本得不到想要的结果,跟踪代码的执行的会发现onFling()事件一直就没有被捕捉到。这正是一开始困扰我的问题,这到底是为什么呢?  
我在讨论组的Gesture detection这个帖子里找到了答案,即我们需要在onCreate中tv.setOnTouchListener(this);之后添加如下一句代码。  
tv.setLongClickable(true);  
只有这样,view才能够处理不同于Tap(轻触)的hold(即ACTION_MOVE,或者多个ACTION_DOWN),我们同样可以通过layout定义中的android:longClickable来做到这一点。  
这次遇到的这个问题和上次MapView中setOnKeyListener遇到的问题挺类似,其实都是对SDK的了解不够全面,遇到了一次记住了就好。不过话说回来,Google在文档方面确实需要加强了,起码可以在OnGestureListener中说明需要满足那些条件才可以保证手势被正确识别。

转载于:https://my.oschina.net/u/1015229/blog/391496

android手势操作滑动效果触摸屏事件处理相关推荐

  1. Android实现圆弧滑动效果之ArcSlidingHelper篇

    前言 我们平时在开发中,难免会遇到一些比较特殊的需求,就比如我们这篇文章的主题,一个关于圆弧滑动的,一般是比较少见的.其实在遇到这些东西时,不要怕,一步步分析他实现原理,问题便能迎刃而解. 前几天一位 ...

  2. Android实现左右滑动效果

    本示例演示在Android中实现图片左右滑动效果.   关于滑动效果,在Android中用得比较多,本示例实现的滑动效果是使用ViewFlipper来实现的,当然也可以使用其它的View来实现.接下来 ...

  3. Android手势操作

    手势操作在我们使用智能设备的过程中奉献了不一样的体验.Android开发中必然会进行手势操作方面的编程.那么它的原理是怎样的呢?我们如何进行手势操作编程呢? 手势操作原理首先,在Android系统中, ...

  4. Android 手势操作GestureDetector

    在很多应用中我们经常会看到一些不同手势的点击事件,例如QQ的消息列表,我们可以通过左滑消息来选择删除或者置顶或者标记为已读,我们也可以通过右滑拖出QQ菜单.有些应用中还会有长按,双击等手势.但是一般情 ...

  5. Android手势操作耍起来!

    目录 前言 初步了解手势操作 六个重写方法 小栗子体验一下 别忘了双击事件 最后 前言 手势操作是Android交互当中至关重要的. 可以说, 如果一个软件没有好的手势操作, 就不能将其定义为移动端的 ...

  6. android horizontalscrollview 动画,Android HorizontalScrollView左右滑动效果

    本文实例为大家分享了Android HorizontalScrollView左右滑动的具体代码,供大家参考,具体内容如下 效果图 一.什么是HorizontalScrollView Horizonta ...

  7. android 手势操作垂直滑动,Android-水平和垂直方向都可滑动的RecycleView

    最近有点忙,项目进度跟的比较紧.最近需求那边让我们写一个左右和上下都可滑动的列表,用来展示多个Title的值.这里我把需求简化了一下.老规矩,先看图. 在看到需求的时候,有在网上看看有没有别人造好的轮 ...

  8. android开发歌词滑动效果_android 实现歌词自动滚动+手指顺畅拖动

    需求: 1.歌词可以跟随播放进度进行自动滑动: 2.可以手指进行歌词顺畅滑动: 3.当前歌词高亮,且置于屏幕的中心: 实现方式一: 也是网上可以搜到的做多的方式:自定义view,继承textview; ...

  9. android开发歌词滑动效果_Android 歌词同步滚动效果

    歌词是播放器类App必不可少的组件,而一般的歌词组件都需要做到歌词的显示与播放进度同步.我们知道,歌词是如下所示的文件: lrc [ti:原来爱情这么伤] [ar:梁咏琪] [al:给自己的情歌] [ ...

最新文章

  1. 第十六节:语法总结(3)(C#6.0和C#7.0新语法)
  2. [hdu4631 Sad Love Story]最近点对,枚举
  3. Python私有化与poperty方法
  4. 近期 AI 领域招聘、招生信息汇总
  5. C# 中base和this关键字
  6. 文本编辑器查看 cprintf颜色_做生信,你需要一款好用的文本编辑器
  7. 阿里巴巴字体库的下载以及三种用法
  8. nginx工作原理、配置以及web服务器的资源请求过程
  9. Golang代码测试:一点到面用测试驱动开发
  10. 替换修改windows xp字体,为windows 7微软雅黑
  11. 《新参者-加贺恭一郎》、《麦田里的守望者》杂记
  12. 计算机游戏 英文作文,电脑游戏英语作文
  13. 生于80年代,穷于10年代,败于90后
  14. 如何求取管壁努塞尔数【转载】
  15. 转换IC CD7833CZ:4x41W汽车音响功率放大电路
  16. 学计算机小升初,小升初微机派位什么意思
  17. 怎么解决云电脑卡顿的问题?
  18. 萌新成长计划(开篇章)
  19. mysql中avg函数如果有空值_对于 AVG 函数,如果列中所有行的值都是 null,那么 AVG 函数返回的值是( )...
  20. 深入学习Java:关于List下标越界源码分析

热门文章

  1. .Net版行号消除器
  2. 在持续交付阶段中的测试覆盖率(译)
  3. 【剑指offer】最长不含重复字符的子字符串
  4. MIMO雷达比幅单脉冲测角精度分析(系统工程与电子技术)
  5. ubuntu 桌面图标设置
  6. 获取异常信息e.printStackTrace()的内容
  7. oracle数据库sql培训,Oracle数据库SQL语言实战培训教程(全面、详细、案例、精讲)套餐...
  8. python2 x与python3 x_python2.x 与 python3.x的不同
  9. 【Paper】2018_多机器人领航-跟随型编队控制
  10. LaTex 并集交集等