修复白屏BUG、UI 边界溢出 BUG

This commit is contained in:
2026-08-09 01:35:48 +08:00
parent 4a357024bc
commit 4385c6941e
24 changed files with 485 additions and 206 deletions
@@ -0,0 +1,164 @@
# 修复 UI 边界溢出与记分页白屏问题
## 问题概述
1. **记分页白屏(严重)**:进入记分页后白屏,由 `OutlinedButton` 收到无限宽度约束导致整个 `Scaffold` 布局失败引起
2. **首页环值分布卡片溢出**`score_distribution_card.dart:86` Column 底部溢出 13px
3. **创建页数字选择器溢出**`point_book_create_page.dart:187` Row 右侧溢出 14px
## 根因分析
### 白屏根因:`SizedBox(height: size)` 与 `Expanded` 的约束冲突
`point_book_edit_page.dart` 第 82-141 行的结构:
```
Expanded( // 给子节点 tight height = 剩余高度 (如 200px)
child: Padding(
child: LayoutBuilder(
builder: (context, constraints) {
final size = constraints.maxWidth; // 如 350px (屏幕宽度)
return SizedBox(
width: size, // 350
height: size, // 350 ← 与 Expanded 的 200px 冲突!
child: GestureDetector(...),
);
},
),
),
)
```
**约束冲突原理**
- `Expanded` 给子节点 `BoxConstraints(minHeight: 200, maxHeight: 200)` (tight)
- `SizedBox(height: 350)` 给子节点 `BoxConstraints(minHeight: 350, maxHeight: 350)` (tight)
- 交集:`minHeight: max(200,350)=350, maxHeight: min(200,350)=200`**350 > 200,不可能约束!**
- 布局失败级联到整个 Column → Scaffold → 白屏
### 环值分布卡片溢出根因
`score_distribution_card.dart` 第 84 行:`maxH = constraints.maxHeight - 28`
柱状图 `_Bar` 的 Column 内容总高度 = count文字(~15) + spacing(4) + bar(最大 maxH=112) + spacing(4) + label文字(~16) = 151px,但可用高度仅 140px,溢出 11-13px。
### 创建页溢出根因
`point_book_create_page.dart` 第 187 行:`_NumberPicker` 内的 Row 包含两个默认尺寸 `IconButton`(各 48px)+ 文字 + 标签文字,在半屏宽度内放不下。
## 修改方案
### 1. `point_book_edit_page.dart` — 修复白屏(关键)
**文件**`lib/features/scoring/presentation/point_book_edit_page.dart`
**行号**82-141
`Expanded > Padding > LayoutBuilder > SizedBox` 结构改为 `Expanded > Padding > Center > AspectRatio > LayoutBuilder`
```dart
// 修改前(第 85-90 行):
child: LayoutBuilder(
builder: (context, constraints) {
final size = constraints.maxWidth;
return SizedBox(
width: size,
height: size,
child: GestureDetector(
// 修改后:
child: Center(
child: AspectRatio(
aspectRatio: 1.0,
child: LayoutBuilder(
builder: (context, constraints) {
final size = constraints.maxWidth;
return GestureDetector(
```
关键变更:
-`Padding``LayoutBuilder` 之间插入 `Center(child: AspectRatio(aspectRatio: 1.0))`
- 删除 `SizedBox(width: size, height: size)` 包装层
- `Center` 松解 `Expanded` 的 tight height 约束 → `AspectRatio` 计算 min(宽,高) 的正方形 → `LayoutBuilder` 获取的 `constraints.maxWidth == constraints.maxHeight` → 无冲突
- `Image.asset``CustomPaint``size: Size(size, size)` 保持不变
- 对应关闭括号:需要增加 `),` (AspectRatio) 和 `),` (Center) 的闭合
### 2. `point_book_create_page.dart` — 修复 Row 溢出 14px
**文件**`lib/features/scoring/presentation/point_book_create_page.dart`
**行号**187-216`_NumberPicker` 的 build 方法)
修改 `_NumberPicker` 中的两个 `IconButton`,使其更紧凑:
```dart
// 修改前(第 193-198 行):
IconButton(
icon: const Icon(Icons.remove_circle_outline),
onPressed: () {
// 修改后:
IconButton(
icon: const Icon(Icons.remove_circle_outline),
iconSize: 20,
visualDensity: VisualDensity.compact,
padding: EdgeInsets.zero,
constraints: const BoxConstraints(),
onPressed: () {
```
同样修改 `add` 按钮(第 207-211 行)。
并将标签文字包裹 `Flexible`(第 190 行):
```dart
// 修改前:
Text(label, style: const TextStyle(fontSize: 13)),
// 修改后:
Flexible(
child: Text(label, style: const TextStyle(fontSize: 13)),
),
```
### 3. `score_distribution_card.dart` — 修复 Column 溢出 13px
**文件**`lib/features/home/presentation/widgets/score_distribution_card.dart`
**行号**:第 84 行
```dart
// 修改前:
final maxH = constraints.maxHeight - 28; // reserve space for label
// 修改后:
final maxH = constraints.maxHeight - 40; // reserve space for count + label
```
将预留空间从 28px 增加到 40px,确保柱子最大高度不会导致 Column 溢出。
### 4. `heatmap_card.dart` — 修复 CustomPaint 尺寸为零(附带修复)
**文件**`lib/features/home/presentation/widgets/heatmap_card.dart`
**行号**:第 29 行
当前 `Stack``CustomPaint` 没有指定 `size`,在 `Stack` 中默认尺寸为 0x0,导致命中点不可见。
```dart
// 修改前(第 29 行):
child: Stack(
alignment: Alignment.center,
children: [
// 修改后:
child: Stack(
fit: StackFit.expand,
alignment: Alignment.center,
children: [
```
添加 `fit: StackFit.expand` 使所有非定位子节点(`Image.asset``CustomPaint`)填满 Stack。
## 验证步骤
1. 运行 `flutter analyze` 确认无错误
2. 启动 APP,进入首页 → 确认无黄色溢出条纹
3. 点击"开始记分" → 进入创建页 → 确认数字选择器无溢出
4. 完成创建 → 进入记分页 → 确认 **不白屏**,靶面正常显示
5. 点击靶面 → 确认命中点准确渲染
6. 返回首页 → 查看热力图 → 确认命中点可见