OnTouch Rotate View 触摸旋转时手指移入布局容器内失控自转问题求助
问题根因
- 核心错误是ACTION_MOVE逻辑中复用了存储触摸坐标的变量
mX、mY:你把计算得到的角度值直接覆盖了原本存坐标的mY,后续计算把角度值当成触摸坐标代入atan2运算,结果完全错误,就会出现视图疯狂自转的问题。 - 次要问题:你当前将触摸监听绑定在旋转按钮
btnrot上,当手指移出按钮区域时,部分ROM的触摸事件采样逻辑异常也可能加剧这个问题。
修复后的实现代码
btnrot.setOnTouchListener(OnTouchListener { v, event -> if (!freeze) { val layoutParams = layGroup.layoutParams as LayoutParams val layBg = v.parent as RelativeLayout val arrayOfInt = IntArray(2) layBg.getLocationInWindow(arrayOfInt) // 单独定义变量存储触摸坐标,不和角度计算变量复用 val touchX = event.rawX.toInt() - arrayOfInt[0] val touchY = event.rawY.toInt() - arrayOfInt[1] when (event.action) { MotionEvent.ACTION_DOWN -> { layGroup.invalidate() startDegree = layGroup.rotation pivx = layoutParams.leftMargin + v.width / 2 pivy = layoutParams.topMargin + v.height / 2 basex = touchX - pivx basey = pivy - touchY } MotionEvent.ACTION_MOVE -> { // 单独定义变量存储角度计算结果,不覆盖坐标变量 val currentDeltaX = touchX - pivx val currentDeltaY = pivy - touchY // 计算初始向量和当前向量的角度差 val baseDegree = Math.toDegrees(atan2(basey.toDouble(), basex.toDouble())) val currentDegree = Math.toDegrees(atan2(currentDeltaY.toDouble(), currentDeltaX.toDouble())) var offsetDegree = (baseDegree - currentDegree).toInt() if (offsetDegree < 0) { offsetDegree += 360 } layGroup.rotation = (startDegree + offsetDegree) % 360f } } return@OnTouchListener true } freeze })
额外优化建议
- 如果需要支持手指移出按钮后仍能正常控制旋转,可以把触摸监听绑定到父布局
layBg上,在ACTION_DOWN时判断触摸点是否落在btnrot范围内再触发旋转逻辑即可。 - 可以增加角度变化阈值,只有角度差超过1°再更新视图旋转,避免小幅度抖动导致的视图跳动。
内容的提问来源于stack exchange,提问作者MidWinterNight
相关产品推荐
相关产品推荐

