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

Flutter自定义绘制SignalBar无法居中对齐问题求助

解决CustomPaint信号图标无法居中对齐的问题

从示意图能看到,信号图标明显偏上,和电池图标、百分比文字不在同一水平线上——问题出在你SignalBar的绘制逻辑里:你用了负的Y坐标来定位信号条,导致信号条整体向上超出了CustomPaint的画布范围,视觉上就会偏移,没法和行内元素对齐。

1. 修复信号条的Y轴偏移问题

修改paint方法里的矩形Y坐标计算,把负偏移改成正偏移,让所有信号条都落在CustomPaint的size范围内,同时让信号条整体垂直居中。

修改后的SignalBar代码:

import 'package:flutter/material.dart';

class SignalBar extends CustomPainter {
  const SignalBar({this.signalStrength = 4});
  final int signalStrength;

  @override
  void paint(Canvas canvas, Size size) {
    var barBorder = Paint()
      ..color = Colors.black
      ..style = PaintingStyle.stroke
      ..strokeWidth = 1.5;
    var barWidth = size.width * 0.15;

    // 计算最长信号条的高度,用于垂直居中计算
    double maxBarHeight = size.height * ((signalStrength - 1) * 0.05 + 0.2);
    double startY = (size.height - maxBarHeight) / 2; // 让信号条整体垂直居中

    // 绘制信号条边框
    for (var i = 0; i < signalStrength; i++) {
      double barHeight = size.height * ((i * 0.05) + 0.2);
      canvas.drawRRect(
          RRect.fromRectAndRadius(
              Rect.fromLTWH(
                  size.width * (i * 0.22),
                  startY + (maxBarHeight - barHeight), // 从下往上排列信号条
                  barWidth,
                  barHeight),
              const Radius.circular(8)),
          barBorder);
    }

    var barFill = Paint()
      ..color = (signalStrength <= 2)
          ? Colors.red
          : (signalStrength <= 3)
              ? Colors.orange
              : Colors.blue.shade600;

    // 绘制信号条填充
    for (var i = 0; i < signalStrength; i++) {
      double barHeight = size.height * ((i * 0.05) + 0.2);
      canvas.drawRRect(
          RRect.fromRectAndRadius(
              Rect.fromLTWH(
                  size.width * (i * 0.22),
                  startY + (maxBarHeight - barHeight),
                  barWidth,
                  barHeight),
              const Radius.circular(8)),
          barFill);
    }
  }

  @override
  bool shouldRepaint(covariant SignalBar oldDelegate) {
    return oldDelegate.signalStrength != signalStrength; // 仅在信号强度变化时重绘,优化性能
  }
}

2. 调整Row中的CustomPaint使用

去掉测试用的Align组件,给CustomPaint设置合适的尺寸,或者用Center包裹确保它在Row内水平居中:

修改后的Row代码片段:

Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: [
    AnimatedBatteryIcon(
        duration: const Duration(seconds: 1),
        chargeValue: stringToInt(data?.batteryValue),
        isCharging: data?.batteryCharging == "1"),
    Text(
      "${data?.batteryValue}%",
      style: const TextStyle(fontWeight: FontWeight.bold),
    ),
    Center(
      child: CustomPaint(
        painter: SignalBar(
            signalStrength: stringToInt(data?.signalbar)),
        size: const Size(20, 25), // 调整尺寸匹配其他元素
      ),
    ),
  ],
)

关键修改说明

  • 移除了负Y偏移,通过计算startY让信号条整体在CustomPaint画布中垂直居中
  • 信号条改为从下往上排列(短条在下、长条在上),符合常规信号图标的视觉习惯
  • 修复了shouldRepaint逻辑,避免不必要的重绘,提升性能
  • 调整CustomPaint的尺寸,让图标大小和电池、文字匹配,更容易对齐

这样修改后,信号图标就能和行内其他元素正常居中对齐了。

内容的提问来源于stack exchange,提问作者Frank nike

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 15:23:14