# Flutter 阴影透出问题

> **问题标签**: `shadow`, `neumorphism`, `transparency`, `boxshadow`  
> **框架**: Flutter  
> **严重程度**: 中等（视觉问题）

---

## 🔍 问题识别

### 自动检测特征

```dart
// 代码模式匹配
BoxShadow(
  color: Color(0x??000000), // 包含黑色阴影
  // ...
)
// + 半透明背景
color: Color(0x??FFFFFF)
```

### 用户描述关键词
- "阴影透出来了"
- "容器比设计稿暗"
- "失去通透感"
- "新拟态效果不对"
- "毛玻璃效果变灰"

### 问题特征
- [ ] 半透明容器颜色比设计稿更暗
- [ ] 容器有 BoxShadow 阴影
- [ ] 阴影包含深色（黑色/灰色）
- [ ] 视觉上失去"玻璃感"或"通透感"

---

## ❌ 常见错误排查路线（避免重复）

| 尝试方向 | 为什么无效 | 浪费时间 |
|----------|-----------|---------|
| 降低容器透明度 | 治标不治本，破坏设计稿规格 | 1-2 轮对话 |
| 修改全局主题 fillColor | 问题不在主题层 | 2-3 轮对话 |
| 调整阴影颜色/大小 | 只要阴影在下方就会透出 | 2-3 轮对话 |
| 使用深色背景模拟 | Hack 方案，不同背景下失效 | 1-2 轮对话 |

**总计浪费**: 6-10 轮对话

---

## ✅ 正确解决方案

### 核心原理

Flutter `BoxShadow` 绘制在容器**下方**，当容器背景半透明时，阴影颜色会透过容器显示出来。

```
┌─────────────────────────┐
│      阴影层（黑色）       │  ← 最底层
├─────────────────────────┤
│   容器层（55%白色）       │  ← 半透明，下面的黑色透出来
├─────────────────────────┤
│      内容层              │
└─────────────────────────┘

结果: 55%白色 + 黑色阴影 = 偏暗的灰色
```

### 解决方法：空心阴影 (Hollow Shadow)

使用 `CustomPainter` 绘制阴影，但裁剪掉中间的容器区域。

```dart
import 'dart:ui' as ui;

class HollowShadowPainter extends CustomPainter {
  final List<BoxShadow> shadows;
  final double radius;

  HollowShadowPainter({required this.shadows, required this.radius});

  @override
  void paint(Canvas canvas, Size size) {
    final RRect shape = RRect.fromRectAndRadius(
      Rect.fromLTWH(0, 0, size.width, size.height),
      Radius.circular(radius),
    );

    final Path shapePath = Path()..addRRect(shape);
    final Path canvasPath = Path()
      ..addRect(Rect.fromLTWH(-500, -500, size.width + 1000, size.height + 1000));

    // 关键：挖空中间区域
    final Path outerPath = Path.combine(
      ui.PathOperation.difference,
      canvasPath,
      shapePath,
    );

    canvas.save();
    canvas.clipPath(outerPath); // 只在外部绘制

    for (final shadow in shadows) {
      final Paint shadowPaint = Paint()
        ..color = shadow.color
        ..maskFilter = MaskFilter.blur(
          BlurStyle.normal, 
          shadow.blurRadius * 0.57735 + 0.5,
        );
      canvas.drawRRect(
        shape.inflate(shadow.spreadRadius).shift(shadow.offset), 
        shadowPaint,
      );
    }

    canvas.restore();
  }

  @override
  bool shouldRepaint(covariant HollowShadowPainter oldDelegate) {
    return oldDelegate.shadows != shadows || oldDelegate.radius != radius;
  }
}
```

### 使用示例

```dart
Widget _buildNeumorphicContainer({required Widget child, double height = 54}) {
  return CustomPaint(
    painter: HollowShadowPainter(
      radius: 16,
      shadows: const [
        BoxShadow(color: Color(0x0D000000), blurRadius: 3, offset: Offset(0, 1)),
        BoxShadow(color: Color(0x14000000), blurRadius: 5, offset: Offset(2, 2)),
        BoxShadow(color: Color(0xE6FFFFFF), blurRadius: 5, offset: Offset(-2, -2)),
      ],
    ),
    child: Container(
      height: height,
      decoration: BoxDecoration(
        color: const Color(0x8CFFFFFF), // 可以放心使用设计稿透明度
        borderRadius: BorderRadius.circular(16),
        border: Border.all(color: const Color(0x99FFFFFF), width: 1),
      ),
      child: child,
    ),
  );
}
```

---

## 📋 适用场景

- ✅ 新拟态 (Neumorphism) 设计
- ✅ 毛玻璃/磨砂玻璃效果
- ✅ 任何需要半透明背景 + 阴影的场景
- ✅ iOS 风格 UI

---

## 🔗 相关案例

- [layout-尺寸不匹配.md](./layout-尺寸不匹配.md) - 新拟态容器尺寸调整
- [input-字段缺失.md](./input-字段缺失.md) - CustomPainter 配合输入框使用

---

**来源**: my_flutter 项目实战经验  
**创建日期**: 2025-12-31  
**最后验证**: 2026-01-16
