重读《Android 开发艺术探索》,本篇是书中的第三章内容的总结。
本章内容包括
View 基础、事件分发、滑动及了解了前面的知识如何解决滑动冲突android是什么系统问题。
更多细节见思维导图






一些代码相关的内容
获取 Tandroid/yunosouchSlop
ViewConfiguration.get(this).scaledTouchSlop
获取 VelocityTracker
// 追踪当前点击事件的速度 val velocityTracker = VelocityTracker.obtain() velocityTracker.addMovement(event) // 先计算 velocityTracker.computeCurrentVelocity(1000) // 获得当前速度 val xVelocity = velocityTracker.xVelocity val yVelocity = velocityTracker.yVelocity ... // 不用使用,需要重置 velocityTracker.clear() velocityTracker.recycle()
使用 GestureDetector
// 创建 GestureDetector 对象 val mGestureDetector = GestureDetector(context, object : GestureDetector.OnGestureListener { override fun onDown(e: MotionEvent?): Boolean { // 触摸的一瞬间 TODO("Not yet implemented") } override fun onShowPress(e: MotionEvent?) { // 触摸屏幕,未松开或拖动 TODO("Not yet implemented") } override fun onSingleTapUp(e: MotionEvent?): Boolean { // 松开,点击行为 TODO("Not yet implemented") } override fun onScroll( e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float, ): Boolean { // 手指按下并拖动,拖动行为 TODO("Not yet implemented") } override fun onLongPress(e: MotionEvent?) { // 长按 TODO("Not yet implemented") } override fun onFling( e1: MotionEvent?, e2: MotionEvent?, velocityX: Float, velocityY: Float, ): Boolean { // 按下,快速滑动后松开,快速滑动行为 TODO("Not yet implemented") } }) // 设置 双击监听 mGestureDetector.setOnDoubleTapListener(object : GestureDetector.OnDoubleTapListener { override fun onSingleTapConfirmed(e: MotionEvent?): Boolean { // 严格的单击行为,是单击而非双击中的一次点击 TODO("Not yet implemented") } override fun onDoubleTap(e: MotionEvent?): Boolean { // 双击,两次单击组成 TODO("Not yet implemented") } override fun onDoubleTapEvent(e: MotionEvent?): Boolean { // 发送双击行为,会被调用多次 TODO("Not yet implemented") } }) // 解决长按屏幕后无法拖动的现象 mGestureDetector.setIsLongpressEnabled(false) // 传入被监听 view 的 event val consume = mGestureDetector.onTouchEvent(event)
使用 Scrollandroid是什么手机牌子er
// 实现弹性滑动 private val mScroller = Scroller(context) private fun smoothScrollTo(destX: Int, destY: Int) { val scrollX = scrollX val delta = destX - scrollX // 1000ms 内滑向 destX, mScroller.startScroll(scrollX, 0, delta, 0, 1000) invalidate() } override fun computeScroll() { super.computeScroll() if (mScroller.computeScrollOffset()) { scrollTo(mScroller.currX, mScroller.currY) postInvalidate() } }
使用外部拦截法解决滑动冲突的主要代码 只需修改父控android/yunos件
// 在父控件中添加以下代码,主要是控制是否要拦截事件,拦截添加根据实际情况添加 // 外部拦截法 override fun onInterceptTouchEvent(event: MotionEvent): Boolean { var intercept = false val x = event.x.toInt() val y = event.y.toInt() when (event.action) { MotionEvent.ACTION_DOWN -> { intercept = false if (!mScroller.isFinished) { mScroller.abortAnimation() intercept = true } } MotionEvent.ACTION_MOVE -> { val deltaX = x - mLastXIntercept val deltaY = y - mLastYIntercept // 当前控件需要拦截当前事件的判断,此处的条件是:横行滑动大于垂直滑动时拦截 intercept = abs(deltaX) > abs(deltaY) } MotionEvent.ACTION_UP -> { intercept = false } } mLastX = x mLastY = y mLastXIntercept = x mLastYIntercept = y return intercept }
使用内部拦截法解决滑动冲突的主要代码 父控件代android是什么系统码
// 内部拦截法 override fun onInterceptTouchEvent(event: MotionEvent): Boolean { val x = event.x.toInt() val y = event.y.toInt() val action = event.action // 不能拦截 ACTION_DOWN 事件,一旦拦截该事件那么所有事件都无法传递给子控件 if (action == MotionEvent.ACTION_DOWN) { mLastX = x mLastY = y if (!mScroller.isFinished) { mScroller.abortAnimation() return true } return false } else { return true } }
子控件代码
// 内部拦截法 override fun dispatchTouchEvent(event: MotionEvent): Boolean { val x = event.x.toInt() val y = event.y.toInt() when (event.action) { MotionEvent.ACTION_DOWN -> { // mParentView 需要被传递给当前控件 mParentView.requestDisallowInterceptTouchEvent(true) } MotionEvent.ACTION_MOVE -> { val deltaX = x - mLastX val deltaY = y - mLastY // 父控件需要拦截该事件的条件 if (abs(deltaX) > abs(deltaY)) { mParentView.requestDisallowInterceptTouchEvent(false) } } MotionEvent.ACTION_UP -> { } } mLastX = x mLastY = y return super.dispatchTouchEvent(event) }
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论(0)