首先是点击事件在不同的布局层次中传递的。

理解Down事件再哪个层次被消费(拦截),后续的Move、Up的点击事件如何传递。

其中ViewGroup中onInterceptTouchEvent方法用来对事件作预处理的,对于Down事件返回true表示要消费这个事件,不再向子View传递。

onInterceptTouchEvent用于改变事件的传递方向。决定传递方向的是返回值,返回为false时事件会传递给子控件,返回值为true时事件会传递给当前控件的onTouchEvent(),这就是所谓的Intercept(拦截)。

[tisa ps:正确的使用方法是,在此方法内仅判断事件是否需要拦截,然后返回。即便需要拦截也应该直接返回true,然后由onTouchEvent方法进行处理。]

onTouchEvent用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。尤其对于ACTION_DOWN事件,返回true,表示我想要处理后续事件;返回false,表示不关心此事件,并返回由父类进行处理。

可能你要问是否消费了又区别吗,反正我已经针对事件编写了处理代码?答案是有区别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。

在没有重写onInterceptTouchEvent()和onTouchEvent()的情况下(他们的返回值都是false), 对上面这个布局,MotionEvent事件的传递顺序如下:

当某个控件的onInterceptTouchEvent()返回值为true时,就会发生截断,事件被传到当前控件的onTouchEvent()。如我们将LayoutView2的onInterceptTouchEvent()返回值为true,则传递流程变成:

如果我们同时将LayoutView2的onInterceptTouchEvent()和onTouchEvent()设置成true,那么LayoutView2将消费被传递的事件,同时后续事件(如跟着ACTION_DOWN的ACTION_MOVE或者ACTION_UP)会直接传给LayoutView2的onTouchEvent(),不传给其他任何控件的任何函数。同时传递给子空间一个ACTION_CANCEL事件。传递流程变成(图中没有画出ACTION_CANCEL事件):

[tisa ps:总体来看, onInterceptTouchEvent是自rootview向下传递, onTouchEvent正好相反。]

基于以上点击事件的传递,可以重写一些ViewGroup,响应其拖动的事件,比如LinearLayout,重写其onInterceptTouchEvent()和onTouchEvent()两个方法可以达到效果(具体看实际布局中子view对事件的消费情况而定)

//true是拦截,false是不拦截。这里只是预处理判断点击的位置,不拦截。

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

if (ev.getAction() == MotionEvent.ACTION_DOWN) {

int x = (int) ev.getX();

int y = (int) ev.getY();

dragSrcPointY = y;

FTLog.d(_TAG, "x=" + x + ",y=" + y);

}

return super.onInterceptTouchEvent(ev);

}

@Override

public boolean onTouchEvent(MotionEvent ev) {

//只有判断是点击触发拖动的区域时,才进行处理。否则不处理,交予FTBounceListView旧逻辑处理。

int action = ev.getAction();

switch (action) {

case MotionEvent.ACTION_DOWN:

//FTLog.e("TMS===down==", "tms");

//bConsumeDown = true;

return true;

//case MotionEvent.ACTION_MOVE:

//FTLog.e("TMS===move==", "tms");

//if (bConsumeDown == false)

//{

//super.onTouchEvent(ev);

//}

//break;

case MotionEvent.ACTION_UP:

FTLog.d(_TAG, "x="+ev.getX()+",y="+ev.getY());

if (ev.getY()

{//向上拖动距离超过20dip,才finish,动画效果。

try {

((Activity) context).finish();

((Activity) context).overridePendingTransition(

R.anim.move_bottom_in, R.anim.move_top_out);

} catch (Exception e) {

e.printStackTrace();

}

}

return true;

default:

break;

}

return super.onTouchEvent(ev);

}

其他视具体情况而定,比如listview的最后一条,某中间区域响应拖动的事件:

//true是拦截,false是不拦截。这里只是预处理判断点击的位置,不拦截。

@Override

public boolean onInterceptTouchEvent(MotionEvent ev) {

if (ev.getAction() == MotionEvent.ACTION_DOWN) {

bConsumeDown = false;

int x = (int) ev.getX();

int y = (int) ev.getY();

dragSrcPosition = pointToPosition(x, y);

dragSrcPointY = y;

if (dragSrcPosition == AdapterView.INVALID_POSITION) {

return super.onInterceptTouchEvent(ev);

}

FTLog.d(_TAG, "x=" + x + ",y=" + y);

FTLog.d(_TAG, "dragSrcPosition==" + dragSrcPosition

+ "getAdapter().getCount()==" + getAdapter().getCount());

if (dragSrcPosition == getAdapter().getCount() - 1

|| dragSrcPosition == getAdapter().getCount() - 2)

{// 最后一条是footer,倒数第二条是数据

ViewGroup itemView = (ViewGroup) getChildAt(dragSrcPosition

- getFirstVisiblePosition());

int itemLeft = itemView.getLeft();

int itemRight = itemView.getRight();

int itemMid = (itemRight + itemLeft) / 2;

FTLog.d(_TAG, "itemLeft==" + itemLeft + ", itemRight="

+ itemRight + ",itemMid=" + itemMid);

if (x > itemMid - 60 && x

bConsumeDown = true;//预处理,判断是点击触发拖动的区域,并不拦截事件

return false;

}

}

}

return super.onInterceptTouchEvent(ev);

}

/**

* 触摸事件

*/

@Override

public boolean onTouchEvent(MotionEvent ev) {

if (bConsumeDown == true && dragSrcPosition != INVALID_POSITION) {

//只有判断是点击触发拖动的区域时,才进行处理。否则不处理,交予FTBounceListView旧逻辑处理。

int action = ev.getAction();

switch (action) {

case MotionEvent.ACTION_DOWN:

//FTLog.e("TMS===down==", "tms");

//bConsumeDown = true;

break;

//case MotionEvent.ACTION_MOVE:

//FTLog.e("TMS===move==", "tms");

//if (bConsumeDown == false)

//{

//super.onTouchEvent(ev);

//}

//break;

case MotionEvent.ACTION_UP:

FTLog.d(_TAG, "x="+ev.getX()+",y="+ev.getY());

if (ev.getY()

{//向上拖动距离超过20dip,才finish,动画效果。

try {

((Activity) context).finish();

((Activity) context).overridePendingTransition(

R.anim.move_bottom_in, R.anim.move_top_out);

} catch (Exception e) {

e.printStackTrace();

}

}

break;

default:

break;

}

return true;

}

return super.onTouchEvent(ev);

}

以上重写ViewGroup的两个方法,对于具体的View来讲,可以setOnTouchLinstener方法,再其OnTouch方法中,用mGestureDetectorOpen.onTouchEvent(event);来响应。

_imageview_room_op_item_open.setOnTouchListener(new OnTouchListener() {

@Override

public boolean onTouch(View v, MotionEvent event) {

mGestureDetectorOpen.onTouchEvent(event);

return true;

}

});

mGestureDetectorOpen = new GestureDetector(this, new OnGestureListener()

{

@Override

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,

float velocityY) {//判断在_imageview_room_op_item_open控件上移动的距离,do something}

}

android layout 点击,Tips_Android点击事件(Down、Move、Up)的分发_重写Layout响应拖动事件...相关推荐

  1. cocos2d ccLayer响应触摸事件方法:CCStandardTouchDelegate 与 CCTargetedTouchDelegate

    cocos2d ccLayer响应触摸事件方法:CCStandardTouchDelegate 与 CCTargetedTouchDelegate    以下内容转载自:http://blog.sin ...

  2. Android 动态添加标签及其点击事件

    在做Android开发的时候,会遇到动态添加标签让用户选择的功能,所以自己写了个例子,运行效果图如下. 标签可以左右滑动进行选择,点击的时候,会弹出toast提示选择或者取消选择了哪个标签.通过动态添 ...

  3. android通知栏的点击事件,Android监听消息通知栏点击事件

    Android监听消息通知栏点击事件 使用BroadCastReceiver 1 新建一个NotificationClickReceiver 类,并且在清单文件中注册!! public class N ...

  4. 程序猿媛一:Android滑动翻页+区域点击事件

    2019独角兽企业重金招聘Python工程师标准>>> 滑动翻页+区域点击事件 ViewPager+GrideView 声明:博文为原创,文章内容为,效果展示,思路阐述,及代码片段. ...

  5. android l 效果,[原]Android L中水波纹点击效果的实现

    博主参加了2014 CSDN博客之星评选,帮我投一票吧. 前言 前段时间android L(android 5.0)出来了,界面上做了一些改动,主要是添加了若干动画和一些新的控件,相信大家对view的 ...

  6. android 点击图标重启,Android应用第一次安装成功点击“打开”后Home键切出应用后再点击桌面图标返回导致应用重启问题的解决方法...

    Android应用第一次安装成功点击"打开"后Home键切出应用后再点击桌面图标返回导致应用重启问题的解决方法 if((getIntent().getFlags() & I ...

  7. Android L中水波纹点击效果的实现

    博主参加了2014 CSDN博客之星评选,帮我投一票吧. 点击给我投票 前言 前段时间android L(android 5.0)出来了,界面上做了一些改动,主要是添加了若干动画和一些新的控件,相信大 ...

  8. android 加号弹出菜单,Android仿微信、qq点击右上角加号弹出操作框

    Android仿微信.qq点击右上角加号弹出操作框,先上图,类似于下图这种,点击加号,会弹出一个对话框,如下图: 微信: 自己实现: 接下来,我们来实现此功能: 其实,实现原理就是,点击"+ ...

  9. Android自定义弹窗模仿微信,Android仿微信、qq点击右上角加号弹出操作框

    Android仿微信.qq点击右上角加号弹出操作框,先上图,类似于下图这种,点击加号,会弹出一个对话框,如下图: 微信: 自己实现: 接下来,我们来实现此功能: 其实,实现原理就是,点击"+ ...

最新文章

  1. java nextline_Java编程语言基础的9根支柱
  2. 微软企业库5.0学习笔记(四)配置企业库
  3. ABAP Subscreen and tabstrip controls
  4. 上海证券携手神策数据,引领普惠金融创新升级
  5. Visual Studio——多字节编码与Unicode码
  6. linux 命令 考试,linux常用命令总结-第一次考试
  7. 大数据新手之路二:安装Flume
  8. php绘制频谱图,一步一步教你实现iOS音频频谱动画(二)
  9. iOS开发-自定义UIAlterView(iOS 7)
  10. Python中fastapi构建的web项目进行docker部署
  11. java学习之自定义异常
  12. java bigdecimal语法_Java Scanner hasNextBigDecimal()方法
  13. hmcl手机版_hmcl启动器app下载
  14. 一个开源的音频分离深度学习项目
  15. 计算机主机箱组装示意图,电脑主机组装图解
  16. 图片批量转换为C语言数组工具
  17. 解锁图案-九宫格有多少种组合?安全吗?用程序来解答
  18. 电商APP的流量及用户运营分析
  19. 蓝桥寒假训练1-2013年第四届蓝桥杯省赛
  20. 微信蓝牙设备开发--添加设备以及获取微信为设备生成的二维码

热门文章

  1. 拿到了B轮融资,但这家创业公司还是被天使投资人玩死了
  2. 【跃迁之路】【448天】刻意练习系列207(2018.04.29)
  3. 【vue】使用vue+element搭建项目,Tree树形控件使用
  4. 域名解析的记录类型区别
  5. Delphi XE2 之 FireMonkey 入门(30) - 数据绑定: TBindingsList: TBindExpression 的 OnAssigningValue 事件...
  6. 网上整理的jQuery插件开发教程
  7. 关于“习惯”的精彩分析
  8. [转] UML类图的几种关系总结
  9. discuz在线人数的实现原理(Discuz6.1.0)
  10. RS485 串口调试如何操作