【maaath】Flutter for OpenHarmony 量角器应用开发实战
本文详细介绍了如何使用 Flutter for OpenHarmony 跨平台框架开发一款功能完备的量角器应用。通过绘制刻度盘、实现交互拖拽、单例服务模式管理全局状态,我们成功在鸿蒙设备上实现了 8 大核心功能。Flutter for OpenHarmony 为开发者提供了强大的跨平台开发能力,一套代码即可同时在 Android、iOS 和 OpenHarmony 设备上运行。使用进行自定义绘制实
Flutter for OpenHarmony 量角器应用开发实战:8大功能打造专业角度测量工具
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
作者:maaath
一、引言
在日常工作和学习中,角度测量是一个常见需求——设计师需要测量图纸角度,建筑工人需要检查屋顶坡度,学生需要验证几何定理。然而,随身携带一个实体量角器并不方便。借助 Flutter for OpenHarmony 跨平台框架,我们可以在鸿蒙设备上开发一款功能完备的量角器应用,将手机或平板变成随身携带的精确测量工具。
本文将从零开始,详细介绍如何使用 Flutter 在 OpenHarmony 平台上构建一款量角器应用,涵盖角度精确测量、拍照测量、历史记录、屏幕校准、单位切换、多角度同时测量、数据导出和语音播报等 8 大核心功能。所有代码均已在 OpenHarmony 设备上验证通过,完整源码请访问 AtomGit(https://atomgit.com)获取。
二、应用架构设计
在开始编码之前,我们先设计应用的架构。量角器应用采用经典的单例服务模式 + 页面分离架构:
- 数据模型层(Models):定义角度线、测量记录、校准数据、导出格式等核心数据结构
- 业务服务层(Services):管理测量历史、校准参数、单位设置、语音开关等全局状态
- UI 展示层(Pages):包含主测量页面、拍照测量页面、历史记录页面、校准页面、导出页面
这种分层架构的优势在于:数据与 UI 分离,服务层作为单例可以在不同页面间共享状态,代码结构清晰,便于后续功能扩展。
三、核心数据模型设计
首先,我们定义量角器的核心数据模型。角度测量涉及两个关键概念:角度线(AngleLine) 和 测量记录(AngleMeasurement)。
// 角度线:由起点和终点定义的一条射线
class AngleLine {
final String id;
double startX;
double startY;
double endX;
double endY;
int colorValue;
AngleLine({
required this.id,
required this.startX,
required this.startY,
required this.endX,
required this.endY,
this.colorValue = 0xFF4A90D9,
});
// 计算该线与水平方向的夹角(度)
double get angle {
final dx = endX - startX;
final dy = endY - startY;
return atan2(dy, dx) * 180.0 / pi;
}
}
// 测量记录:包含两条或多条角度线及其测量结果
class AngleMeasurement {
final String id;
final List<AngleLine> lines;
final DateTime timestamp;
final MeasurementMode mode;
String? note;
bool isFavorite;
// 计算两条线之间的夹角
double get angleDegrees {
if (lines.length < 2) return 0;
final angle1 = lines[0].angle;
final angle2 = lines[1].angle;
var diff = (angle2 - angle1).abs();
if (diff > 180) diff = 360 - diff;
return double.parse(diff.toStringAsFixed(2));
}
}
AngleLine 通过 atan2 函数计算每条线与水平方向的夹角,AngleMeasurement 则通过两条线的角度差计算出最终夹角。代码中还对超过 180° 的情况做了处理,确保始终返回较小的夹角值。
四、量角器刻度盘绘制
量角器的核心视觉组件是刻度盘。我们使用 Flutter 的 CustomPainter 在 Canvas 上绘制一个 360° 的量角器刻度盘,包含主刻度(每 30°)、次刻度(每 10°)和细刻度(每 5°)。
class _ProtractorPainter extends CustomPainter {
final double radius;
final double centerX;
final double centerY;
void _drawProtractorScale(Canvas canvas) {
final center = Offset(centerX, centerY);
// 绘制外圈刻度
for (int i = 0; i < 360; i += 5) {
final rad = i * pi / 180.0;
final isMajor = i % 30 == 0; // 主刻度
final isMedium = i % 10 == 0; // 中刻度
final innerR = isMajor ? radius - 15 : (isMedium ? radius - 10 : radius - 5);
final outerR = radius + 5;
final inner = Offset(centerX + innerR * cos(rad), centerY + innerR * sin(rad));
final outer = Offset(centerX + outerR * cos(rad), centerY + outerR * sin(rad));
tickPaint.strokeWidth = isMajor ? 1.5 : 0.5;
canvas.drawLine(inner, outer, tickPaint);
// 主刻度旁标注角度数值
if (isMajor) {
final labelPos = Offset(
centerX + (radius - 25) * cos(rad),
centerY + (radius - 25) * sin(rad),
);
// 绘制角度标签...
}
}
}
}
通过三角函数 cos 和 sin 计算每个刻度线的起点和终点位置,配合 strokeWidth 区分不同层级的刻度,实现了与传统量角器一致的视觉体验。
五、交互式角度测量
用户可以通过拖拽测量线的端点来调整角度,实现交互式测量。每个端点都是一个可拖拽的圆形控件:
Widget _buildDraggablePoint(double x, double y, int lineIndex) {
return Positioned(
left: x - 16,
top: y - 16,
child: GestureDetector(
onTap: () => setState(() => _selectedLineIndex = lineIndex),
onPanUpdate: (details) {
setState(() {
final newX = (x + details.delta.dx).clamp(20.0, 340.0);
final newY = (y + details.delta.dy).clamp(20.0, 420.0);
_lines[lineIndex].endX = newX;
_lines[lineIndex].endY = newY;
});
},
child: Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: Color(_lines[lineIndex].colorValue),
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 3),
),
),
),
);
}
GestureDetector 的 onPanUpdate 回调实时更新端点坐标,setState 触发 UI 重绘,从而实现流畅的拖拽交互体验。端点坐标通过 clamp 限制在有效范围内,防止拖拽出界。
六、拍照测量模式
拍照测量模式允许用户在照片上标记测量点,自动计算角度。我们模拟了一个建筑屋顶场景,用户点击画面添加测量点,系统自动连线并计算角度:
void _addPoint(Offset point) {
setState(() {
_points.add(point);
if (_points.length >= 2) {
final lastTwo = _points.sublist(_points.length - 2);
_lines.add(AngleLine(
id: 'photo_line_${_lines.length}',
startX: lastTwo[0].dx,
startY: lastTwo[0].dy,
endX: lastTwo[1].dx,
endY: lastTwo[1].dy,
colorValue: _lineColors[_lines.length % _lineColors.length],
));
}
});
}
每点击两个点形成一条测量线,至少需要四条点(两条线)才能计算出一个角度。这种设计模拟了真实场景中在照片上画辅助线测量的过程。
七、屏幕校准功能
由于不同设备的屏幕尺寸和触控精度存在差异,我们提供了屏幕校准功能。校准采用 5 点校准法——用户依次点击屏幕上显示的 5 个十字准星标记,系统自动计算偏移量和缩放因子:
void _calculateCalibration() {
double sumDx = 0;
double sumDy = 0;
for (int i = 0; i < _calibrationPoints.length; i++) {
sumDx += _targetPoints[i].dx - _calibrationPoints[i].dx;
sumDy += _targetPoints[i].dy - _calibrationPoints[i].dy;
}
_offsetX = sumDx / _calibrationPoints.length;
_offsetY = sumDy / _calibrationPoints.length;
// 计算缩放因子
final actualDist = (_calibrationPoints[1] - _calibrationPoints[0]).distance;
final targetDist = (_targetPoints[1] - _targetPoints[0]).distance;
_scaleFactor = targetDist / actualDist;
_service.updateCalibration(_offsetX, _offsetY, _scaleFactor);
}
校准参数通过 ProtractorService 单例保存,后续所有测量都会自动应用校准补偿,确保在不同设备上都能获得准确的测量结果。
八、数据导出与语音播报
应用支持将测量历史导出为 CSV 或 JSON 格式,方便用户进行数据分析或存档:
String generateCsvExport() {
final buffer = StringBuffer();
buffer.writeln('ID,角度(度),角度(弧度),模式,时间,备注');
for (final m in _history) {
buffer.writeln(
'${m.id},${m.angleDegrees},${m.getAngleInUnit(AngleUnit.radian)},'
'${m.mode.label},${m.timestamp.toIso8601String()},${m.note ?? ""}'
);
}
return buffer.toString();
}
语音播报功能则在测量完成后通过对话框播报测量结果,提升用户体验。用户可以在设置中随时开关语音功能。
九、运行效果截图
以下是在 OpenHarmony 设备上运行量角器应用的截图:
| 功能模块 | 截图 |
|---|
主测量页面 | 量角器刻度盘清晰显示,两条测量线分别用蓝色和红色标识,夹角区域高亮显示,顶部实时显示角度数值 45.00° |
| 拍照测量 | 深色主题的拍照测量界面,网格背景上已标记测量点,系统自动连线并计算角度 |
| 历史记录 | 列表展示所有测量记录,包含角度值、测量模式标签、时间戳,支持收藏和语音回放 |
| 屏幕校准 | 5 点校准界面,绿色标记已校准点,橙色标记当前待校准点,校准完成后显示偏移量和缩放因子 |

| 数据导出 | CSV/JSON 格式选择,全部记录/仅收藏范围选择,导出结果预览和复制功能 |
注:由于截图文件较大,完整截图请查看项目仓库中的
screenshots/目录。
十、总结与展望
本文详细介绍了如何使用 Flutter for OpenHarmony 跨平台框架开发一款功能完备的量角器应用。通过 CustomPainter 绘制刻度盘、GestureDetector 实现交互拖拽、单例服务模式管理全局状态,我们成功在鸿蒙设备上实现了 8 大核心功能。
Flutter for OpenHarmony 为开发者提供了强大的跨平台开发能力,一套代码即可同时在 Android、iOS 和 OpenHarmony 设备上运行。通过本文的实践,读者可以掌握以下技能:
- 使用
CustomPainter进行自定义绘制 - 实现拖拽交互和实时角度计算
- 单例服务模式在 Flutter 中的应用
- 数据导出(CSV/JSON)的实现
- 屏幕校准算法的设计与实现
未来可以进一步扩展的功能包括:AR 增强现实测量、云端数据同步、角度测量精度优化、更多导出格式支持等。欢迎访问 AtomGit(https://atomgit.com)获取完整源码,加入开源鸿蒙跨平台社区(https://openharmonycrossplatform.csdn.net)交流讨论,共同推动 Flutter for OpenHarmony 生态发展。
更多推荐




所有评论(0)