双指缩放逻辑
概述
双指缩放功能允许用户通过双指手势放大或缩小K线图,改变K线的显示宽度,从而查看更多或更少的数据。
使用的API
1. ScaleGestureDetector
作用:Android系统提供的手势检测器,用于检测双指缩放手势。
关键API:
ScaleGestureDetector(context, listener)- 创建手势检测器onTouchEvent(event)- 处理触摸事件detector.scaleFactor- 获取缩放因子(>1放大,<1缩小)
实现代码:
kotlin
// 创建缩放手势检测器
private val scaleGestureDetector: ScaleGestureDetector by lazy {
ScaleGestureDetector(context, this)
}
// 实现接口
class ScrollableAndScalableKLineView : View, ScaleGestureDetector.OnScaleGestureListener {
// 实现三个回调方法
override fun onScaleBegin(detector: ScaleGestureDetector): Boolean
override fun onScale(detector: ScaleGestureDetector): Boolean
override fun onScaleEnd(detector: ScaleGestureDetector)
}
2. MotionEvent
作用:检测触摸点数量,区分单指和多指操作。
关键API:
event.pointerCount- 获取触摸点数量event.actionMasked- 获取触摸事件类型
核心概念
缩放比例 klineScaleX
- 作用:控制K线宽度的缩放倍数
- 范围:0.5 ~ 2.0(可配置)
- 默认值:1.0(不缩放)
- 影响 :缩放后,每根K线的宽度 = 原始宽度 ×
klineScaleX
缩放后的K线宽度
kotlin
// 缩放后的总宽度(包括K线宽度和间距)
private fun getScaledTotalCandleWidth(): Float {
return config.getTotalCandleWidth() * klineScaleX
}
缩放实现原理
1. 手势检测
使用 ScaleGestureDetector 检测双指缩放手势,通过 onScale() 回调累积缩放因子:
kotlin
override fun onScale(detector: ScaleGestureDetector): Boolean {
klineScaleX *= detector.scaleFactor // 累积缩放
klineScaleX = klineScaleX.coerceIn(minScaleX, maxScaleX) // 限制范围
invalidate() // 重绘
return true
}
2. 手势冲突处理
问题 :ScaleGestureDetector 和 GestureDetector 可能同时处理触摸事件。
解决方案:
- 使用
scaleGestureDetector.isInProgress判断是否正在缩放,如果正在缩放则不处理滚动 - 在
onScaleBegin()中停止滚动动画,避免同时进行
kotlin
override fun onTouchEvent(event: MotionEvent): Boolean {
scaleGestureDetector.onTouchEvent(event)
// 如果正在缩放,不处理滚动
if (scaleGestureDetector.isInProgress) {
return true
}
// 处理滚动...
}
需要调整的地方
缩放需要在以下地方应用:K线宽度、间距、滚动边界、translateX、可见范围、滚动位置。所有计算都使用 getScaledTotalCandleWidth() 获取缩放后的宽度。
缩放与滚动的协调
先处理缩放,如果正在缩放则不处理滚动。缩放后重新计算滚动边界,自动调整滚动位置。
效果
