Android艺术探索笔记

第三章 View的事件体系

2019-01-10  本文已影响0人  ByteStefan
  1. TouchSlop
    系统所能识别的最小滑动距离。可通过 ViewConfiguration.get(getContext).getScaledTouchSlop() 获取这个常量。

  2. VelocityTracker
    速度追踪,用于追踪手指在滑动过程中的速度,包括水平和竖直方向。

//在 onTouchEvent 中跟踪
override fun onTouchEvent(event: MotionEvent?): Boolean {
    val velocityTracker = VelocityTracker.obtain()
    velocityTracker.addMovement(event)
    //计算1s内的速度
    velocityTracker.computeCurrentVelocity(1000)
    Log.e("ASD123","${velocityTracker.xVelocity} --- ${velocityTracker.yVelocity}")
    return super.onTouchEvent(event)
}

//在不需要的时候清除回收掉
velocityTracker.clear()
velocityTracker.recycle()

  1. GestureDetector
    手势监听,用于辅助检测用户的单击、滑动、长按、双击等行为。
val mGestureDetector by lazy {
    GestureDetector(this, object : GestureDetector.OnGestureListener {
        override fun onShowPress(p0: MotionEvent?) {
            Log.e("ASD123", "手指轻轻触摸屏幕,尚未松开和拖动")
        }

        override fun onSingleTapUp(p0: MotionEvent?): Boolean {
            Log.e("ASD123", "手指轻轻触摸屏幕松开--单击")
            return true
        }

        override fun onDown(p0: MotionEvent?): Boolean {
            Log.e("ASD123", "手指轻轻触摸屏幕")
            return true
        }

        override fun onFling(p0: MotionEvent?, p1: MotionEvent?, p2: Float, p3: Float): Boolean {
            Log.e("ASD123", "手指按下屏幕并拖动 -- 拖动")
            return true
        }

        override fun onScroll(p0: MotionEvent?, p1: MotionEvent?, p2: Float, p3: Float): Boolean {
            Log.e("ASD123", "快速滑动")
            return true
        }

        override fun onLongPress(p0: MotionEvent?) {
            Log.e("ASD123", "手指按下屏幕不放 -- 长按")
        }
    })
}

override fun onTouchEvent(event: MotionEvent?): Boolean {
    mGestureDetector.setOnDoubleTapListener(object :GestureDetector.OnDoubleTapListener{
        override fun onDoubleTap(p0: MotionEvent?): Boolean {
            Log.e("ASD123", "手指两次连续单击 -- 双击")
            return true
        }
    
        override fun onDoubleTapEvent(p0: MotionEvent?): Boolean {
            Log.e("ASD123", "发生了双击行为,在双击期间,ACTION_DOWN、ACTION_MOVE、ACTION_UP都会触法此回调")
            return true           
        }
    
        override fun onSingleTapConfirmed(p0: MotionEvent?): Boolean {
            Log.e("ASD123", "严格的单击行为")
            return true           
        }
    })
    return mGestureDetector.onTouchEvent(event)
}
  1. View 的事件分发机制
    dispatchTouchEvent -> onInterceptTouchEvent -> onTouchEvent
    事件传递的机制:
    ① 同一个事件序列是指从手指接触屏幕的那一刻起,到手指离开屏幕的那一刻结束,在这个过程中产生的一系列事件,这个事件序列以 down 事件开始,中间含有数量不定的 move 事件,最终以 up 事件结束。
    ② 正常情况下,一个事件序列只能被一个 View 拦截且消耗。除非通过特殊手段,如一个 View 将本该自己处理的事件通过 onTouchEvent 强行传递给其他 View 处理。
    ③ 某个 View 一旦决定拦截,那么这一个事件序列都只能由它来处理,并且它的 onInterceptTouchEvent 不会再被调用。
    ④ 某个 View 一旦开始处理事件,如果它不消耗 ACTION_DOWN 事件(onTouchEvent 返回了 false),那么同一事件序列中的其他事件都不会再交给它来处理,并且事件将重新交由它的父元素去处理,即调用父元素的 onTuchEvent。
    ⑤ 如果 View 不消耗除 ACTION_DOWN 以外的其他事件,那么这个点击事件会消失,此时父元素的 onTouchEvent 并不会都调用,并且当前 View 可以持续收到后续事件,最终这些消失的点击事件会传递到 Activity 处理。
    ⑥ ViewGroup 默认不拦截任何时间,即 ViewGroup 的 onInterceptTouchEvent 方法默认返回 false
    ⑦ View 没有 onInterceptTouchEvent 方法,一旦有点击事件传递给它,那么它的 onTouchEvent 方法就会被调用。
    ⑧ View 的 onTouchEvent 默认都会消耗事件(返回 true),除非它是不可点击的(clickable 和 longClickable 同时为 false)。View 的 longClickable 属性默认都为 false,clickable 属性要分情况,Button 默认为 true,TextView 默认为 false
    ⑨ View 的 enable 属性不影响 onTouchEvent 的默认返回值。
    ⑩ onClick 会发生的前提是当前 View 是可点击的,并且它收到了 down 和 up 事件。
    ⑪ 事件传递过程是由外向内的,即事件总是先传递给父元素,然后再由父元素分发给子 View,通过 requestDisallowInterceptTouchEvent 方法可以在子元素中干预父元素的事件分发过程,但是 ACTION_DOWN 事件除外。
上一篇下一篇

猜你喜欢

热点阅读