Files
android-ruler/docs/superpowers/specs/2026-05-19-android-ruler-design.md

158 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Android 标尺测量应用 - 设计文档
## 概述
一款利用手机屏幕作为物理标尺的测量工具应用。支持屏幕标尺测量和拍照标注两种模式,通过屏幕 DPI + 手动校准保证测量精度。
**技术栈**Kotlin + Jetpack Compose + Material 3
**最低 API**24 (Android 7.0)
**主要依赖**CameraX、DataStore Preferences
---
## 架构
### 顶层导航
```
┌──────────────────────────────────────────┐
│ 🔧 设置AppBar 右上角图标) │
├──────────────────────────────────────────┤
│ │
│ 标尺测量模式 / 拍照标注模式 │
│ │
├──────────────────────────────────────────┤
│ 📏 标尺 | 📷 拍照(底部导航栏) │
└──────────────────────────────────────────┘
```
底部导航栏切换两种模式。右上角齿轮图标进入设置页面。设置页面使用独立 Screen 展示。
### 模式一:标尺测量
屏幕显示物理标尺。竖屏时纵向绘制,横屏时横向绘制。支持滚动查看完整量程。
**绘制规则**
- 三级刻度cm 线最长标注数字、0.5cm 线中等、mm 线(最短)
- 测量标记:用户点击放置起点(绿色)、终点(红色),可拖拽微调
- 结果展示:两点间距精确到 0.5mm
**关键计算**
```
pixelPerCm = (dpi / 2.54) × cmCorrectionFactor
totalCm = screenSide / pixelPerCm
```
### 模式二:拍照标注
```
拍照 → 预览确认 → 编辑标注 → 合成保存
```
- **拍照**CameraX 实现相机预览和拍照
- **标注编辑**:在照片上叠加一个虚拟小标尺图
- 小标尺是主标尺的缩略版(指定长度如 2/3/5/10cm样式一致
- 手势:单指拖拽移动、双指旋转 + 缩放
- 底部切换标尺长度
- **合成保存**:照片 Bitmap + 标尺 Canvas 绘制合并为一张图,通过 MediaStore 保存到相册
### 设置页面
| 设置项 | 类型 | 说明 |
|--------|------|------|
| 标尺校准 | 交互页面 | 拖拽滑块对齐真实尺子的 10cm保存修正系数 |
| 默认方向 | 选择 | 竖屏 / 横屏 / 自适应 |
| 拍照标尺默认长度 | 选择 | 2cm / 5cm / 10cm |
| 关于 | 信息 | 版本号等 |
---
## 状态管理
### 单一 ViewModel
```kotlin
data class RulerUiState(
val orientation: Orientation,
val pixelPerCm: Float,
val scrollOffset: Float,
val markStartCm: Float?,
val markEndCm: Float?,
val currentMode: Mode, // RULER / PHOTO
val photoBitmap: Bitmap?,
val overlayRulerLength: Float,
val overlayPosition: Offset,
val overlayScale: Float,
val overlayRotation: Float,
val showSettings: Boolean,
val cmCorrectionFactor: Float,
)
```
### DataStore 持久化
| Key | 类型 | 默认值 |
|-----|------|--------|
| `cm_correction_factor` | Float | 1.0 |
| `is_calibrated` | Boolean | false |
| `default_orientation` | String | "auto" |
| `default_ruler_length` | Float | 3.0 |
统一封装为 `SettingsRepository`
---
## 项目结构
```
app/src/main/java/com/example/androidruler/
├── MainActivity.kt
├── RulerApplication.kt
├── ui/
│ ├── RulerScreen.kt
│ ├── RulerCanvas.kt
│ ├── Markers.kt
│ ├── ControlBar.kt
│ ├── photo/
│ │ ├── PhotoMarkScreen.kt
│ │ ├── CameraCapture.kt
│ │ ├── PhotoEditor.kt
│ │ └── RulerOverlay.kt
│ ├── settings/
│ │ ├── SettingsScreen.kt
│ │ └── CalibrationScreen.kt
│ └── util/
│ └── ImageSaver.kt
├── viewmodel/
│ └── RulerViewModel.kt
├── data/
│ └── SettingsRepository.kt
└── theme/
└── Theme.kt
```
---
## AndroidManifest 权限
```xml
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
```
---
## 边界情况
| 场景 | 处理 |
|------|------|
| DPI 返回异常(如 160 | 弹窗提示手动校准 |
| 首次启动无校准数据 | 用自动 DPI 先行绘制,顶部显示校准提示条 |
| 屏幕旋转 | 标记点位置按比例换算保留 |
| 标记点极短距离(<1mm | 显示 "< 1mm" |
| 拍照权限拒绝 | 提示引导去设置页开启 |
| 相机不可用 | 模拟器/无相机设备降级为纯标尺模式 |
| 图片保存失败 | Toast 提示重试 |