博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2018.03.08、View的事件分发机制笔记
阅读量:7117 次
发布时间:2019-06-28

本文共 5971 字,大约阅读时间需要 19 分钟。

一、

1、Activity页面构成元素

  • 1)在activity 中 通过 setContentView() 方法设置为根布局。在每一个Activity 中 都包含一个Window 对象,它由 PhoneWindow来实现
  • 2)PhoneWindow 将一个 DecorView 设置为整个应用窗口的根View。
  • 3)DecorView,由TitleView 和ContentView组成, 前者承载的是一个Actionbar,后者承载的是一个FrameLayout,

2、MotionEvent和TouchSlop

  • 1)手指接触屏幕后 会产生以下的事件:
ACTION_DOWN // 收支接触ACTION_MOVE // 手指在屏幕上移动ACTION_UP //手指从屏幕松开ACTION_CANCEL //取消复制代码
  • 2)MotionEvent 对象获取的 点击的 x 和 y ,

    ①.使用 getX / getY 获取的是相对于当前View左上角的x和y,
    ②.而 getRawX / getRawY 获取的是相对于手机屏幕左上角的坐标。

  • 3)TouchSlop:是系统所能识别的最小滑动距离,小于它则视未发生滑动,在不同的设备上获取的值不同。通过:

ViewConfiguration.get(getContext()).getScaledTouchSlop() //获得复制代码

3、VelocityTracker、GestureDetector和Scroller

  • 1)VelocityTracker:速度追踪,用于追踪滑动过程中的速度,包括水平和竖直速度。
//1.在 onTouchEvent 方法中追踪当前事件的速度VelocityTracker  tracker = VelocityTracker.obtain();tracker.addMovement(event);//2.获取当前速度tracker.computeCurrentVelocity(1000);//计算速度int xVelocity = (int) tracker.getXVelocity();int yVelocity = (int) tracker.getYVelocity();//3.在不需要的时候重置回收内存tracker.recycle();复制代码
  • 2)GestureDetector:用于检测单击、滑动、长按、双击等手势。
    首先要实现 GestureDetector.OnGestureListener接口,如果需要双击,则需实现 GestureDetector.OnDoubleTapListener 接口;
//设置监听mGestureDetector = new GestureDetector(this);//避免长按后无法拖动,自己测试时发现不设置,长按后也可以拖动mGestureDetector.setIsLongpressEnabled(false);复制代码
  • 3)Scroller:弹性滑动,可是实现有过度效果的滑动,View 的 ScrollTo/ScrollBy 都是瞬间滑动完成的。

4、View 的滑动

  • 1)View的滑动主要有如下三种方式:
    • scrollTo /scrollBy :适合对view 的内容改变;
    • 动画: 主要用于没有交互的View 和实现复杂的动画效果;
    • 改变布局参数:操作稍微复杂,适合有交互的View 。
  • 2)View 的 ScrollTo/ScrollBy 方法
public void scrollTo(int x, int y) {      if (mScrollX != x || mScrollY != y) {          int oldX = mScrollX;          int oldY = mScrollY;          mScrollX = x;          mScrollY = y;          invalidateParentCaches();          onScrollChanged(mScrollX, mScrollY, oldX, oldY);          if (!awakenScrollBars()) {              postInvalidateOnAnimation();          }      }  }  public void scrollBy(int x, int y) {      scrollTo(mScrollX + x, mScrollY + y);  }复制代码

其中 scrollBy 调用的是 scrollTo,它实现了使用当前位置的相对滑动,而scrollTo 是基于所传参数的绝对滑动.

  • 3)使用动画
    通过动画为View 添加平移效果,View 的 tanslationX 和 tanslationY 属性,可以采用传统的动画和属性动画。
  • 4)改变布局参数
    通过改变View 的LayoutParams 使得 View 重新布局实现滑动。
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)                mButton.getLayoutParams();params.width += 100;params.leftMargin += 100;mButton.setLayoutParams(params);  // 或者  mButton.requestLayout();复制代码

5、弹性滑动

为了避免 滑动的生硬,可以采用弹性滑动,提高用户体验。

这里主要有 :Scroller、动画、延时三种方式。

  • 1)Scroller 的典型使用,主要是 invalidate方法起的作用。
Scroller mScroller = new Scroller(context);/** * 滑动到指定位置 * * @param destX  X 滑动距离 * @param destY  Y 滑动距离 */private void smoothScrollTo(int destX, int destY) {    //滑动起点X    int scrollX = getScrollX();    //滑动起点Y    int scrollY = getScrollY();    //1000 ms内慢慢滑向 (destX,destY)    mScroller.startScroll(scrollX, scrollY, destX, destY, 1000);    //重绘    invalidate();} /** * 使View 不断重绘 */@Overridepublic void computeScroll() {    /**     *  computeScrollOffset 方法通过时间流逝百分比计算 scrollX和scrollY      *  返回true 表示滑动未结束     */    if (mScroller.computeScrollOffset()) {        //滑动到当前位置,通过小幅度滑动实现弹性滑动        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());        //再次重绘        postInvalidate();    }}复制代码
  • 2)对于延时达到弹性滑动,主要是利用 了Handler 或者 View 的 postDelayed 方法,或者线程的 sleep方法。

6、View 的事件分发机制

  • 1)所有的Touch事件都封装到 MotionEvent 里面;
  • 2)事件处理包括三种情况,分别为:传递—-dispatchTouchEvent()函数、拦截——onInterceptTouchEvent()函数、消费—-onTouchEvent()函数和OnTouchListener;
  • 3)事件类型分为 ACTION_DOWN, ACTION_UP, ACTION_MOVE , ACTION_POINTER_DOWN, ACTION_POINTER_UP , ACTION_CANCEL 等,每个事件都是以 ACTION_DOWN 开始 ACTION_UP 结束。

用下面伪代码表示事件分发过程及其关系:

//事件分发public boolean dispatchTouchEvent(MotionEvent event) {    boolean consume = false;    //是否被拦截    if (onInterceptTouchEvent(event))    {        //被拦截,处理事件        consume = onTouchEvent(event);    } else {        //未被拦截,向下分发        consume = childView.dispatchTouchEvent(event);    }    return consume;}复制代码

1、activity --->ViewGroup --->view 正常流程:

  • 1)当activity dispatchTouchEvent() 返回 true :代表事件停止分发,activity 的onTouchEvent()方法不执行。其子view也接受不到事件。
  • 2)ViewGroup onInterceptTouchEvent() 返回ture时,onTouchEvent() 也返回 true时;

ViewGroup

①、
ViewGroup oninterceptTouchEnent 返回 ture时,表示:传递给子View的事件被拦截了,
ViewGroup onTouchEvent() 返回 true时,表示:该事件被VieWGroup自身消费了,不传递给父View的onTouch方法中处理了。
代码:

EmptyViewGroup: onInterceptTouchEvent--->ACTION_DOWNEmptyViewGroup: onTouchEvent--->ACTION_DOWN...EmptyViewGroup: onTouchEvent--->ACTION_MOVE...EmptyViewGroup: onTouchEvent--->ACTION_UP复制代码

②、

ViewGroup oninterceptTouchEnent 返回 ture时,表示:传递给子View事件被拦截了,
ViewGroup onTouchEvent() 返回 false时,表示:ViewGroup也不处理此事件,交给上层父View(avtivity)的OnTouchEvent()方法处理。
代码:

//viewGroup只消费 ACTION_DOWN 事件EmptyViewGroup: onInterceptTouchEvent--->ACTION_DOWNEmptyViewGroup: onTouchEvent--->ACTION_DOWN//activity 将事件消费DemoActivity: onTouchEvent--->ACTION_DOWN...DemoActivity: onTouchEvent--->ACTION_MOVE...DemoActivity: onTouchEvent--->ACTION_UP复制代码

③、 ViewGroup onInterceptTouchEvent 返回 false时,表示事件传递给子View,不拦截。

ViewGroup onTouchEvent() 返回 false时,ViewGroup也不处理此事件,交给上层父View(avtivity)的OnTouchEvent()方法处理。
View onTouchEvent() 返回 true: 该子View消费了此事件。不传递到ViewGroup的OnTouchEvent()方法中。

EmptyViewGroup: onInterceptTouchEvent--->ACTION_DOWNEmptyView: onTouchEvent--->ACTION_DOWNEmptyViewGroup: onInterceptTouchEvent--->ACTION_MOVEEmptyView: onTouchEvent--->ACTION_MOVE...EmptyViewGroup: onInterceptTouchEvent--->ACTION_UPEmptyView: onTouchEvent--->ACTION_UP复制代码

④、 ViewGroup onInterceptTouchEvent 返回 false时,表示事件传递给子View,不拦截。

ViewGroup onTouchEvent() 返回 false时,ViewGroup也不处理此事件,交给上层父View(avtivity)的OnTouchEvent()方法处理。
View onTouchEvent() 返回 false: 该子View不消费了此事件。传递到ViewGroup的OnTouchEvent()方法中。

EmptyViewGroup: onInterceptTouchEvent--->ACTION_DOWNEmptyView: onTouchEvent--->ACTION_DOWNEmptyViewGroup: onTouchEvent--->ACTION_DOWNDemoActivity: onTouchEvent--->ACTION_DOWNDemoActivity: onTouchEvent--->ACTION_MOVE...DemoActivity: onTouchEvent--->ACTION_UP复制代码

由于activity作为顶级的View,当activity 中所有得子View 都不消费onTouchEvent()事件时,ativity的OnTouchEvent() 无论返回true/false。该activity都会消费用户触发的事件。在onTouchEvent()中。

转载地址:http://tzdel.baihongyu.com/

你可能感兴趣的文章
两个栈实现一个队列
查看>>
Why? 在C++中调用被C编译后的函数,要在声明的前面加extern "C"
查看>>
EhCache 记录
查看>>
【20190404】MySQL疑难杂症-1034
查看>>
glob及IO重定向
查看>>
在使用rsync远端rsync: Failed to exec ssh: No such错误
查看>>
11-26yum安装
查看>>
采用shc工具加密Shell脚本
查看>>
搭建centos7+apache+mongodb+php环境
查看>>
base虚拟机的安装 和 varnish(rhel6.5)
查看>>
MongoDB入门
查看>>
DOCKER存储驱动之总览
查看>>
JEESZ分布式系统环境安装
查看>>
上网本磁盘被格式化了的资料找到法子
查看>>
Java中静态变量(类变量)、实例变量、局部变量和成员变量
查看>>
svn服务搭建
查看>>
Android 4.0 平台特性
查看>>
图片验证码的JAVA工具类
查看>>
Perl 上安装Math::Base36
查看>>
基于弹性堆栈(ELK堆栈)的日志分析、存储及展示
查看>>