一个支持双指缩放和单指拖拽的 Android 自定义布局容器。
- 双指缩放:支持 0.5x - 5.0x 的缩放范围
- 单指拖拽:当内容超出边界时支持平移
- 智能边界:内容小于容器时自动居中,大于容器时允许拖拽
- 子视图支持:正确处理子视图的触摸事件传递
触摸事件 → 手势识别 → 状态更新 → 渲染变换 → 子视图事件转换
- 状态管理:使用
currentScale、translateX/Y记录变换状态 - 手势检测:
ScaleGestureDetector处理缩放,触摸阈值检测拖拽 - 渲染变换:Canvas 的
translate()和scale()实现视觉效果 - 事件分发:坐标转换确保子视图正确接收触摸事件
// 渲染变换
canvas.translate(translateX, translateY)
canvas.scale(currentScale, currentScale, 0f, 0f)
// 坐标转换
val transformedX = (x - translateX) / currentScale
val transformedY = (y - translateY) / currentScale问题:双指缩放和单指拖拽可能冲突
解决:通过 isScaling 和 isDragging 状态标志区分手势类型
问题:缩放后子视图无法正确响应触摸 解决:实现坐标转换,将屏幕坐标转换为子视图坐标
问题:不同缩放比例下的边界计算复杂
解决:统一使用 clampTranslations() 方法处理所有边界情况
问题:频繁重绘影响性能
解决:只在状态真正改变时调用 invalidate(),使用 coerceIn() 优化边界计算
// 在布局中使用
<com.opoojkk.scalablelayout.ScalableLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 你的子视图 -->
</com.opoojkk.scalablelayout.ScalableLayout>
// 代码控制
scalableLayout.zoomIn() // 放大
scalableLayout.zoomOut() // 缩小
scalableLayout.reset() // 重置
scalableLayout.setScale(2.0f) // 设置缩放比例