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

Flutter中解决篮球计分器Text控件溢出与屏幕适配问题

解决Flutter篮球计分器数字溢出问题

你的问题核心是固定字号的Text控件在数字位数增加时,宽度超出父容器范围导致溢出,以下是几种实用的解决方案:

方法1:用FittedBox自动适配(最推荐)

FittedBox会自动缩放子组件以适配父容器的可用空间,无需手动计算字号,是最简洁的解决方案。只需把显示分数的Text包裹在FittedBox中,并给父容器一个合理的宽度约束:

// 替换Team A的分数Text部分
SizedBox(
  // 占屏幕宽度的35%,可根据布局调整比例
  width: MediaQuery.of(context).size.width * 0.35,
  child: FittedBox(
    fit: BoxFit.contain, // 保持文本比例,不拉伸
    child: Text(
      '$numOfPointsTeamA',
      style: const TextStyle(fontWeight: FontWeight.w400),
      // 可保留fontSize作为最大允许字号,超过则自动缩小
    ),
  ),
)

Team B的分数部分做同样修改即可。

方法2:使用第三方库auto_size_text实现精细控制

如果需要限制最小字号、多行适配等更精细的需求,可以使用auto_size_text库:

  1. 先在pubspec.yaml添加依赖:
dependencies:
  auto_size_text: ^3.0.0
  1. 替换分数Text:
import 'package:auto_size_text/auto_size_text.dart';

// ...

AutoSizeText(
  '$numOfPointsTeamA',
  style: const TextStyle(fontWeight: FontWeight.w400),
  maxFontSize: 200, // 最大字号
  minFontSize: 50,  // 最小字号,避免太小看不清
  textAlign: TextAlign.center,
)

方法3:根据数字位数动态设置字号

如果不想用第三方库,也可以根据数字的长度手动切换字号:

Text(
  '$numOfPointsTeamA',
  style: TextStyle(
    fontSize: switch(numOfPointsTeamA.toString().length) {
      1 => 200,
      2 => 150,
      3 => 100,
      _ => 80, // 更多位数时的字号
    },
    fontWeight: FontWeight.w400,
  ),
)

修改后的完整代码示例

这里给出用FittedBox优化后的完整HomePage代码:

class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int numOfPointsTeamA = 0;
  int numOfPointsTeamB = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.orange,
        title: const Text(
          'Basketball Points Counter',
          style: TextStyle(fontSize: 23),
        ),
      ),
      body: Padding(
        padding:
            const EdgeInsets.only(top: 30.0, left: 20, right: 20, bottom: 30),
        child: Column(
          children: [
            SizedBox(
              height: 468,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Column(children: [
                    const Text(
                      'Team A',
                      style:
                          TextStyle(fontSize: 35, fontWeight: FontWeight.w400),
                    ),
                    const SizedBox(
                      height: 20,
                    ),
                    // 修改这里:用FittedBox包裹Text
                    SizedBox(
                      width: MediaQuery.of(context).size.width * 0.35,
                      child: FittedBox(
                        fit: BoxFit.contain,
                        child: Text(
                          '$numOfPointsTeamA',
                          style: const TextStyle(fontWeight: FontWeight.w400),
                        ),
                      ),
                    ),
                    const SizedBox(
                      height: 15,
                    ),
                    ElevatedButton(
                      onPressed: () {
                        setState(() {
                          numOfPointsTeamA++;
                        });
                      },
                      style: ElevatedButton.styleFrom(primary: Colors.orange),
                      child: const Text(
                        'Add 1 point',
                        style: TextStyle(color: Colors.black, fontSize: 20),
                      ),
                    ),
                    const SizedBox(
                      height: 7,
                    ),
                    ElevatedButton(
                      onPressed: () {
                        setState(() {
                          numOfPointsTeamA += 2;
                        });
                      },
                      style: ElevatedButton.styleFrom(primary: Colors.orange),
                      child: const Text(
                        'Add 2 point',
                        style: TextStyle(color: Colors.black, fontSize: 20),
                      ),
                    ),
                    const SizedBox(
                      height: 7,
                    ),
                    ElevatedButton(
                      onPressed: () {
                        setState(() {
                          numOfPointsTeamA += 3;
                        });
                      },
                      style: ElevatedButton.styleFrom(primary: Colors.orange),
                      child: const Text(
                        'Add 3 point',
                        style: TextStyle(color: Colors.black, fontSize: 20),
                      ),
                    ),
                  ]),
                  const VerticalDivider(
                    color: Colors.grey,
                    thickness: 0.5,
                    width: 70,
                  ),
                  Column(children: [
                    const Text(
                      'Team B',
                      style:
                          TextStyle(fontSize: 35, fontWeight: FontWeight.w400),
                    ),
                    const SizedBox(
                      height: 20,
                    ),
                    // 修改这里:用FittedBox包裹Text
                    SizedBox(
                      width: MediaQuery.of(context).size.width * 0.35,
                      child: FittedBox(
                        fit: BoxFit.contain,
                        child: Text(
                          '$numOfPointsTeamB',
                          style: const TextStyle(fontWeight: FontWeight.w400),
                        ),
                      ),
                    ),
                    const SizedBox(
                      height: 15,
                    ),
                    ElevatedButton(
                      onPressed: () {
                        setState(() {
                          numOfPointsTeamB++;
                        });
                      },
                      style: ElevatedButton.styleFrom(primary: Colors.orange),
                      child: const Text(
                        'Add 1 point',
                        style: TextStyle(color: Colors.black, fontSize: 20),
                      ),
                    ),
                    const SizedBox(
                      height: 7,
                    ),
                    ElevatedButton(
                      onPressed: () {
                        setState(() {
                          numOfPointsTeamB += 2;
                        });
                      },
                      style: ElevatedButton.styleFrom(primary: Colors.orange),
                      child: const Text(
                        'Add 2 point',
                        style: TextStyle(color: Colors.black, fontSize: 20),
                      ),
                    ),
                    const SizedBox(
                      height: 7,
                    ),
                    ElevatedButton(
                      onPressed: () {
                        setState(() {
                          numOfPointsTeamB += 3;
                        });
                      },
                      style: ElevatedButton.styleFrom(primary: Colors.orange),
                      child: const Text(
                        'Add 3 point',
                        style: TextStyle(color: Colors.black, fontSize: 20),
                      ),
                    ),
                  ]),
                ],
              ),
            ),
            const SizedBox(
              height: 70,
            ),
            ElevatedButton(
                onPressed: () {
                  setState(() {
                    numOfPointsTeamA = 0;
                    numOfPointsTeamB = 0;
                  });
                },
                style: ElevatedButton.styleFrom(primary: Colors.orange),
                child: const Text(
                  'Reset',
                  style: TextStyle(
                      color: Colors.black,
                      fontSize: 25,
                      fontWeight: FontWeight.w500),
                ))
          ],
        ),
      ),
    );
  }
}

内容的提问来源于stack exchange,提问作者Mohamed Gamal Mohamed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 19:39:25