You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter 无需SyncFusion等授权插件实现体重身高线性标尺及单位换算

体重/身高线性刻度标尺实现方案

1 Custom Paint 绘制实现步骤

  • 先定义刻度基础配置:单个刻度的像素宽度、最小/最大数值、刻度步长(比如体重步长设为0.1kg)、长/短刻度的长度、配色
  • 计算可见刻度范围:根据当前滚动偏移,算出当前可视区域内需要绘制的刻度起始和结束下标,避免绘制不可见内容提升性能
  • 区分刻度样式:整数值对应长刻度+数值标签,小数位对应短刻度无标签;中间选中位置的刻度用高亮色、更长的尺寸突出显示
  • 滚动偏移转数值逻辑:当前选中数值 = 最小数值 + (滚动偏移量 / 单个刻度像素宽度) * 刻度步长,计算结果保留对应小数位即可

2 单位联动逻辑实现

统一用kg作为内部计算基准值,换算规则为 1kg = 2.20462lb,对应双向换算公式:

  • kg转lb:lb数值 = kg数值 * 2.20462
  • lb转kg:kg数值 = lb数值 / 2.20462

联动逻辑:

  • 任意单位的标尺滑动触发数值变更时,先更新基准kg数值,再通过换算公式计算另一单位的对应数值,同步更新另一标尺的滚动位置和输入框显示
  • 输入框手动修改数值时,先判定当前输入的单位,换算为基准kg值后,再同步更新两个标尺的位置和另一单位的输入框数值

3 核心代码示例(Flutter 环境)

刻度绘制核心逻辑

class RulerPainter extends CustomPainter {
  final double scrollOffset;
  final double selectedValue;
  final double minValue;
  final double maxValue;
  final double step = 0.1;
  final double scaleWidth = 8; // 单个刻度占8像素宽度

  RulerPainter({required this.scrollOffset, required this.selectedValue, required this.minValue, required this.maxValue});

  @override
  void paint(Canvas canvas, Size size) {
    final normalPaint = Paint()..color = Colors.grey.shade300..strokeWidth = 1;
    final highlightPaint = Paint()..color = Colors.blue..strokeWidth = 2;
    final centerX = size.width / 2;

    // 绘制所有可见刻度
    final startIndex = (scrollOffset / scaleWidth).floor() - 20;
    final endIndex = (scrollOffset + size.width) ~/ scaleWidth + 20;
    for (int i = startIndex; i <= endIndex; i++) {
      if (i < 0 || minValue + i * step > maxValue) continue;
      final x = i * scaleWidth - scrollOffset;
      final currentValue = minValue + i * step;
      // 整数值刻度更长,且显示文本
      final scaleHeight = currentValue % 1 == 0 ? 30 : 15;
      final paint = (currentValue - selectedValue).abs() < 0.05 ? highlightPaint : normalPaint;
      canvas.drawLine(Offset(x, 0), Offset(x, scaleHeight), paint);
      if (currentValue % 1 == 0) {
        TextSpan span = TextSpan(text: currentValue.toInt().toString(), style: TextStyle(color: Colors.grey, fontSize: 12));
        TextPainter tp = TextPainter(text: span, textDirection: TextDirection.ltr)..layout();
        tp.paint(canvas, Offset(x - tp.width / 2, scaleHeight + 5));
      }
    }
    // 绘制中间选中指示器
    canvas.drawLine(Offset(centerX, 0), Offset(centerX, 40), highlightPaint);
  }

  @override
  bool shouldRepaint(covariant RulerPainter oldDelegate) {
    return oldDelegate.scrollOffset != scrollOffset || oldDelegate.selectedValue != selectedValue;
  }
}

单位联动逻辑

class WeightController extends ChangeNotifier {
  // 内部统一用kg作为基准存储
  double _weightKg = 55.0;
  double get weightKg => _weightKg;
  double get weightLb => _weightKg * 2.20462;

  // 切换kg数值
  void updateByKg(double kg) {
    _weightKg = kg;
    notifyListeners();
  }

  // 切换lb数值
  void updateByLb(double lb) {
    _weightKg = lb / 2.20462;
    notifyListeners();
  }
}

4 实现效果预览

标尺效果演示

内容的提问来源于stack exchange,提问作者Vamsee.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 15:45:04