修复白屏BUG、UI 边界溢出 BUG
This commit is contained in:
@@ -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. 返回首页 → 查看热力图 → 确认命中点可见
|
||||
Reference in New Issue
Block a user