158 lines
4.8 KiB
Markdown
158 lines
4.8 KiB
Markdown
|
|
# 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 提示重试 |
|