Flutter层叠布局 #

一、Stack #

1.1 基本用法 #

Stack允许子Widget层叠放置,后面的Widget会覆盖前面的。

dart
Stack({
  Key? key,
  AlignmentGeometry alignment = AlignmentDirectional.topStart,
  TextDirection? textDirection,
  StackFit fit = StackFit.loose,
  Clip clipBehavior = Clip.hardEdge,
  List<Widget> children = const <Widget>[],
})

Stack(
  children: [
    Container(
      width: 200,
      height: 200,
      color: Colors.red,
    ),
    Container(
      width: 150,
      height: 150,
      color: Colors.green,
    ),
    Container(
      width: 100,
      height: 100,
      color: Colors.blue,
    ),
  ],
)

1.2 alignment属性 #

控制子Widget的对齐方式:

dart
Stack(
  alignment: Alignment.center,
  children: [
    Container(width: 200, height: 200, color: Colors.red),
    Container(width: 100, height: 100, color: Colors.blue),
  ],
)

Alignment.topLeft
Alignment.topCenter
Alignment.topRight
Alignment.centerLeft
Alignment.center
Alignment.centerRight
Alignment.bottomLeft
Alignment.bottomCenter
Alignment.bottomRight

1.3 fit属性 #

控制子Widget的尺寸:

dart
Stack(
  fit: StackFit.loose,
  children: [...],
)

StackFit.loose
StackFit.expand
StackFit.passthrough

1.4 clipBehavior属性 #

控制溢出裁剪:

dart
Stack(
  clipBehavior: Clip.none,
  children: [...],
)

Clip.none
Clip.hardEdge
Clip.antiAlias
Clip.antiAliasWithSaveLayer

二、Positioned #

2.1 基本用法 #

Positioned用于控制子Widget在Stack中的位置。

dart
Positioned({
  Key? key,
  double? left,
  double? top,
  double? right,
  double? bottom,
  double? width,
  double? height,
  Widget? child,
})

Stack(
  children: [
    Container(color: Colors.grey.shade200),
    Positioned(
      left: 20,
      top: 20,
      child: Container(
        width: 100,
        height: 100,
        color: Colors.red,
      ),
    ),
    Positioned(
      right: 20,
      bottom: 20,
      child: Container(
        width: 100,
        height: 100,
        color: Colors.blue,
      ),
    ),
  ],
)

2.2 填充父容器 #

dart
Stack(
  children: [
    Positioned.fill(
      child: Container(color: Colors.red),
    ),
  ],
)

2.3 相对定位 #

dart
Stack(
  children: [
    Positioned(
      left: 10,
      right: 10,
      top: 10,
      bottom: 10,
      child: Container(color: Colors.blue),
    ),
  ],
)

2.4 居中定位 #

dart
Stack(
  children: [
    Container(color: Colors.grey.shade200),
    Positioned(
      top: 0,
      left: 0,
      right: 0,
      bottom: 0,
      child: Center(
        child: Container(
          width: 100,
          height: 100,
          color: Colors.red,
        ),
      ),
    ),
  ],
)

三、IndexedStack #

3.1 基本用法 #

IndexedStack只显示指定索引的子Widget。

dart
IndexedStack({
  Key? key,
  AlignmentGeometry alignment = AlignmentDirectional.topStart,
  TextDirection? textDirection,
  StackFit sizing = StackFit.loose,
  int index = 0,
  List<Widget> children = const <Widget>[],
})

IndexedStack(
  index: _currentIndex,
  children: [
    Container(color: Colors.red, child: Center(child: Text('Page 1'))),
    Container(color: Colors.green, child: Center(child: Text('Page 2'))),
    Container(color: Colors.blue, child: Center(child: Text('Page 3'))),
  ],
)

3.2 切换页面 #

dart
class IndexedStackDemo extends StatefulWidget {
  @override
  State<IndexedStackDemo> createState() => _IndexedStackDemoState();
}

class _IndexedStackDemoState extends State<IndexedStackDemo> {
  int _currentIndex = 0;
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: IndexedStack(
        index: _currentIndex,
        children: [
          Page1(),
          Page2(),
          Page3(),
        ],
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _currentIndex,
        onTap: (index) {
          setState(() {
            _currentIndex = index;
          });
        },
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
          BottomNavigationBarItem(icon: Icon(Icons.search), label: 'Search'),
          BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Profile'),
        ],
      ),
    );
  }
}

四、实战示例 #

4.1 图片角标 #

dart
Stack(
  children: [
    Image.network(
      'https://example.com/image.jpg',
      width: 200,
      height: 150,
      fit: BoxFit.cover,
    ),
    Positioned(
      top: 8,
      right: 8,
      child: Container(
        padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
        decoration: BoxDecoration(
          color: Colors.red,
          borderRadius: BorderRadius.circular(4),
        ),
        child: Text(
          'NEW',
          style: TextStyle(color: Colors.white, fontSize: 12),
        ),
      ),
    ),
  ],
)

4.2 头像角标 #

dart
Stack(
  children: [
    CircleAvatar(
      radius: 30,
      backgroundImage: NetworkImage('https://example.com/avatar.jpg'),
    ),
    Positioned(
      right: 0,
      bottom: 0,
      child: Container(
        width: 20,
        height: 20,
        decoration: BoxDecoration(
          color: Colors.green,
          shape: BoxShape.circle,
          border: Border.all(color: Colors.white, width: 2),
        ),
      ),
    ),
  ],
)

4.3 卡片悬浮效果 #

dart
Stack(
  clipBehavior: Clip.none,
  children: [
    Container(
      width: 200,
      height: 120,
      decoration: BoxDecoration(
        color: Colors.white,
        borderRadius: BorderRadius.circular(8),
        boxShadow: [
          BoxShadow(
            color: Colors.black12,
            blurRadius: 8,
            offset: Offset(0, 4),
          ),
        ],
      ),
    ),
    Positioned(
      top: -20,
      left: 20,
      child: Container(
        width: 60,
        height: 60,
        decoration: BoxDecoration(
          color: Colors.blue,
          borderRadius: BorderRadius.circular(8),
          boxShadow: [
            BoxShadow(
              color: Colors.black26,
              blurRadius: 8,
            ),
          ],
        ),
        child: Icon(Icons.star, color: Colors.white),
      ),
    ),
  ],
)

4.4 进度条 #

dart
Stack(
  children: [
    Container(
      height: 8,
      decoration: BoxDecoration(
        color: Colors.grey.shade300,
        borderRadius: BorderRadius.circular(4),
      ),
    ),
    FractionallySizedBox(
      widthFactor: 0.7,
      child: Container(
        height: 8,
        decoration: BoxDecoration(
          color: Colors.blue,
          borderRadius: BorderRadius.circular(4),
        ),
      ),
    ),
  ],
)

4.5 播放按钮覆盖 #

dart
Stack(
  alignment: Alignment.center,
  children: [
    Image.network(
      'https://example.com/thumbnail.jpg',
      width: double.infinity,
      height: 200,
      fit: BoxFit.cover,
    ),
    Container(
      width: 60,
      height: 60,
      decoration: BoxDecoration(
        color: Colors.black45,
        shape: BoxShape.circle,
      ),
      child: Icon(Icons.play_arrow, color: Colors.white, size: 36),
    ),
    Positioned(
      bottom: 8,
      right: 8,
      child: Container(
        padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
        decoration: BoxDecoration(
          color: Colors.black54,
          borderRadius: BorderRadius.circular(4),
        ),
        child: Text(
          '3:45',
          style: TextStyle(color: Colors.white),
        ),
      ),
    ),
  ],
)

五、总结 #

5.1 核心Widget #

Widget 说明
Stack 层叠容器
Positioned 位置控制
IndexedStack 索引显示

5.2 下一步 #

掌握了层叠布局后,让我们学习 样式与主题

最后更新:2026-03-28