【flutter for open harmony】第三方库Flutter 鸿蒙版 尺子工具 实战指南(适配 1.0.0)✨

Flutter 三方库 cached_network_image 的鸿蒙化适配与实战指南
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net

本文详细介绍如何在Flutter鸿蒙应用中实现屏幕尺子工具,包括刻度绘制、触摸测量和校准功能。

一、前言

屏幕尺子是利用手机屏幕进行简单测量的实用工具,可以测量小物体的长度。本文将介绍如何在Flutter鸿蒙应用中实现屏幕尺子功能。

二、效果展示

在这里插入图片描述

2.1 功能特性

功能 描述
刻度显示 显示厘米和毫米刻度
触摸测量 通过滑动测量距离
校准功能 调整像素与厘米的比例
实时显示 实时显示测量结果

三、项目背景与目标

3.1 项目背景

在日常生活中,有时需要快速测量小物体的长度,但没有实体尺子。屏幕尺子工具可以解决这个问题。

3.2 项目目标

  • 实现刻度绘制功能
  • 实现触摸测量功能
  • 实现校准功能
  • 实时显示测量结果

四、技术架构设计

4.1 架构概述

尺子工具使用Flutter的CustomPaint绘制刻度,通过GestureDetector处理触摸事件,实现测量功能。

4.2 测量原理

通过像素与厘米的比例关系计算实际长度:

  • 公式:厘米 = 像素 / 像素每厘米
  • 默认值:37.8像素/厘米(约等于96 DPI)

五、详细实现

5.1 Flutter端实现

import 'dart:math';
import 'package:flutter/material.dart';

class RulerToolPage extends StatefulWidget {
  const RulerToolPage({super.key});

  
  State<RulerToolPage> createState() => _RulerToolPageState();
}

class _RulerToolPageState extends State<RulerToolPage> {
  double _startX = 0;
  double _endX = 0;
  bool _isMeasuring = false;
  double _pixelsPerCm = 37.8;

  double get _distance => (_endX - _startX).abs();
  double get _cmDistance => _distance / _pixelsPerCm;

  void _onPanStart(DragStartDetails details) {
    setState(() {
      _startX = details.localPosition.dx;
      _endX = details.localPosition.dx;
      _isMeasuring = true;
    });
  }

  void _onPanUpdate(DragUpdateDetails details) {
    setState(() {
      _endX = details.localPosition.dx;
    });
  }

  void _onPanEnd(DragEndDetails details) {
    setState(() {
      _isMeasuring = false;
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('尺子工具'),
        centerTitle: true,
        backgroundColor: Colors.brown,
        foregroundColor: Colors.white,
      ),
      body: Column(
        children: [
          Container(
            padding: const EdgeInsets.all(16),
            color: Colors.brown.withOpacity(0.1),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Icon(Icons.straighten, size: 32, color: Colors.brown),
                const SizedBox(width: 16),
                Text(
                  '${_cmDistance.toStringAsFixed(2)} cm',
                  style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold, color: Colors.brown),
                ),
              ],
            ),
          ),
          Expanded(
            child: GestureDetector(
              onPanStart: _onPanStart,
              onPanUpdate: _onPanUpdate,
              onPanEnd: _onPanEnd,
              child: Container(
                color: Colors.grey[100],
                child: CustomPaint(
                  painter: RulerPainter(_startX, _endX, _isMeasuring, _pixelsPerCm),
                  size: Size.infinite,
                ),
              ),
            ),
          ),
          Container(
            padding: const EdgeInsets.all(16),
            child: Column(
              children: [
                const Text('校准', style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
                const SizedBox(height: 8),
                Row(
                  children: [
                    const Text('像素/厘米:'),
                    Expanded(
                      child: Slider(
                        value: _pixelsPerCm,
                        min: 20,
                        max: 60,
                        divisions: 40,
                        label: _pixelsPerCm.toStringAsFixed(1),
                        onChanged: (v) => setState(() => _pixelsPerCm = v),
                      ),
                    ),
                    Text(_pixelsPerCm.toStringAsFixed(1)),
                  ],
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class RulerPainter extends CustomPainter {
  final double startX;
  final double endX;
  final bool isMeasuring;
  final double pixelsPerCm;

  RulerPainter(this.startX, this.endX, this.isMeasuring, this.pixelsPerCm);

  
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.brown
      ..strokeWidth = 1;

    final textPainter = TextPainter(textDirection: TextDirection.ltr);

    for (double x = 0; x < size.width; x += pixelsPerCm / 10) {
      final cm = x / pixelsPerCm;
      final isCm = (cm % 1).abs() < 0.01;
      final isHalfCm = ((cm + 0.5) % 1).abs() < 0.01;
      
      final lineLength = isCm ? 30.0 : (isHalfCm ? 20.0 : 10.0);
      canvas.drawLine(Offset(x, 0), Offset(x, lineLength), paint);

      if (isCm) {
        textPainter.text = TextSpan(
          text: cm.toInt().toString(),
          style: const TextStyle(color: Colors.brown, fontSize: 12),
        );
        textPainter.layout();
        textPainter.paint(canvas, Offset(x - textPainter.width / 2, 35));
      }
    }

    if (isMeasuring || startX != endX) {
      final measurePaint = Paint()
        ..color = Colors.red
        ..strokeWidth = 2;
      
      canvas.drawLine(Offset(startX, size.height / 2), Offset(endX, size.height / 2), measurePaint);
      
      canvas.drawCircle(Offset(startX, size.height / 2), 8, Paint()..color = Colors.red);
      canvas.drawCircle(Offset(endX, size.height / 2), 8, Paint()..color = Colors.red);
    }
  }

  
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}

5.2 核心功能解析

刻度绘制

使用CustomPainter绘制刻度线,厘米刻度最长,半厘米次之,毫米最短。

触摸测量

通过GestureDetector的onPanStart、onPanUpdate、onPanEnd处理触摸事件。

校准功能

通过Slider调整像素与厘米的比例,适应不同屏幕密度。

六、实际应用场景

6.1 日常测量

测量小物体长度,如硬币、纸张等。

6.2 学习工具

学生学习时进行简单测量。

6.3 工作辅助

工作中快速测量小零件尺寸。

七、优化建议

7.1 多方向测量

支持水平和垂直两个方向的测量。

7.2 历史记录

保存测量历史,方便查看。

7.3 单位切换

支持厘米、英寸等单位切换。

八、常见问题与解决方案

8.1 测量不准确

使用校准功能调整像素与厘米的比例。

8.2 刻度显示不全

检查屏幕尺寸和绘制范围是否匹配。

8.3 触摸响应问题

确保GestureDetector正确包裹CustomPaint。

九、总结

本文详细介绍了Flutter鸿蒙尺子工具的实现过程,包括刻度绘制、触摸测量和校准功能。通过本实例,开发者可以掌握Flutter自定义绘制、手势处理等关键技术点。

十、参考资料

  • Flutter官方文档:https://flutter.dev
  • HarmonyOS开发者文档:https://developer.harmonyos.com
  • Flutter中国社区:https://flutter-io.cn
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐