绘制K线第五章:双指放大缩小

双指缩放逻辑

概述

双指缩放功能允许用户通过双指手势放大或缩小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. 手势冲突处理

问题ScaleGestureDetectorGestureDetector 可能同时处理触摸事件。

解决方案

  • 使用 scaleGestureDetector.isInProgress 判断是否正在缩放,如果正在缩放则不处理滚动
  • onScaleBegin() 中停止滚动动画,避免同时进行
kotlin 复制代码
override fun onTouchEvent(event: MotionEvent): Boolean {
    scaleGestureDetector.onTouchEvent(event)
    
    // 如果正在缩放,不处理滚动
    if (scaleGestureDetector.isInProgress) {
        return true
    }
    
    // 处理滚动...
}

需要调整的地方

缩放需要在以下地方应用:K线宽度、间距、滚动边界、translateX、可见范围、滚动位置。所有计算都使用 getScaledTotalCandleWidth() 获取缩放后的宽度。

缩放与滚动的协调

先处理缩放,如果正在缩放则不处理滚动。缩放后重新计算滚动边界,自动调整滚动位置。

效果

相关推荐
HLC++10 小时前
Linux的进程间通信
android·linux·服务器
爱笑鱼14 小时前
Binder(二):AIDL 生成的 Proxy、Stub 和 Parcel 到底在做什么?
android
爱笑鱼14 小时前
Binder(一):一次方法调用,究竟怎样跨进程执行?
android
壮哥_icon15 小时前
【Android 系统开发】使用 BAT 脚本高效自动化管理 /system/priv-app/ 系统应用(安装与卸载)
android·运维·自动化
用户693717500138416 小时前
Claude Code终端日志Token占用实测:一个过滤器砍掉60%-90%
android·前端·后端
蝉蜕日记17 小时前
AccumuPDF高级版 v2.57 | 视图文转换PDF,合并分割压缩
android·智能手机·pdf·生活·软件需求
吐了啊取名字太难17 小时前
美颜系统AI修图本地跑并支持Mac、win、安卓、iOS不卡顿
android·人工智能·windows·数码相机·mac·ai编程
阿pin18 小时前
Android随笔-Retrofit
android·retrofit
想取一个与众不同的名字好难18 小时前
安卓自定义颜色选择器
android
我命由我1234519 小时前
Android 开发问题:java.lang.NoSuchMethodError:No virtual method readAllBytes()
android·java·java-ee·kotlin·android studio·android-studio·android runtime