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

Flutter如何实现Column溢出时可滚动、空间充足时自动撑开布局

实现方案

使用CustomScrollView搭配SliverFillRemaining组件即可完美实现需求,无需手动判断布局高度或切换组件类型,无额外性能损耗:

  • 当顶部内容高度小于侧边栏可用高度时,SliverFillRemaining自动填充剩余空间,将底部容器固定在侧边栏底部
  • 当顶部内容高度超出可用高度时,整体进入滚动状态,底部容器跟随内容一同滚动

修改后完整代码

import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  @override
  State<MyWidget> createState() {
    return MyWidgetState();
  }
}

class MyWidgetState extends State<MyWidget> {
  List<int> items = [1];

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: [
        SliverList(
          delegate: SliverChildListDelegate([
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                IconButton(
                  icon: const Icon(Icons.add),
                  onPressed: () {
                    setState(() {
                      items.add(items.last + 1);
                    });
                  },
                ),
                IconButton(
                  icon: const Icon(Icons.delete),
                  onPressed: () {
                    setState(() {
                      if (items.length != 1) items.removeLast();
                    });
                  },
                ),
              ],
            ),
            for (final item in items)
              MyAnimatedWidget(
                child: SizedBox(
                  height: 200,
                  child: Center(
                    child: Text('Top content item $item'),
                  ),
                ),
              ),
          ]),
        ),
        SliverFillRemaining(
          hasScrollBody: false,
          child: Align(
            alignment: Alignment.bottomCenter,
            child: Container(
              alignment: Alignment.center,
              decoration: BoxDecoration(border: Border.all()),
              height: 200,
              child: Text('Bottom content'),
            ),
          ),
        )
      ],
    );
  }
}

class MyAnimatedWidget extends StatefulWidget {
  final Widget? child;

  const MyAnimatedWidget({this.child, Key? key}) : super(key: key);

  @override
  State<MyAnimatedWidget> createState() {
    return MyAnimatedWidgetState();
  }
}

class MyAnimatedWidgetState extends State<MyAnimatedWidget>
    with SingleTickerProviderStateMixin {
  late AnimationController controller;

  @override
  initState() {
    controller = AnimationController(
        value: 0, duration: const Duration(seconds: 1), vsync: this);
    controller.animateTo(1, curve: Curves.linear);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: controller,
        builder: (context, child) {
          return SizedBox(height: 200 * controller.value, child: widget.child);
        });
  }
}

关键说明

  • 必须将SliverFillRemaining的hasScrollBody属性设为false,避免出现滑动冲突
  • 所有布局适配逻辑由Flutter框架层处理,不需要额外监听组件尺寸变化,性能和原生布局一致
  • 原有组件的状态可以完全保留,不需要额外做状态持久化处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 08:45:05