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

Flutter:实现CustomScrollView内滚动内容的动态高度(含吸顶效果)

问题:实现底部弹窗固定头部、底部按钮且自适应高度

我想要实现如图所示的效果,但一直理不清思路:
示例效果

目前我尝试用SliverPinnedHeader(配合CustomScrollView组件)实现顶部头部固定,用StickySideWidget.bottom实现底部按钮固定。但因为当前组件嵌套在Column中,必须使用Expanded组件才能在列表内容较多时实现滚动,可这也导致内容较少时仍会占据全屏高度。我希望找到一种无需使用Expanded且不破坏现有功能的方法,同时尽可能避免引入不必要的第三方库。

简化后的代码

import 'package:flutter/material.dart';
import 'package:shared/widgets/commons/safe_area.dart';
import 'package:sliver_tools/sliver_tools.dart';

class DemoWidget extends StatelessWidget {
  DemoWidget({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child: ElevatedButton(
                child: Text('Demo'),
                onPressed: () => showModalBottomSheet(
                      backgroundColor: Colors.white,
                      isScrollControlled: true,
                      context: context,
                      builder: (context) => DemoContent(),
                    ))));
  }
}

class DemoContent extends StatelessWidget {
  DemoContent({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final items = List.filled(20, '');

    final bottomSheetClosingLine = Padding(
      padding: const EdgeInsets.only(bottom: 32),
      child: Center(child: Container(color: Colors.grey, height: 4, width: 64)),
    );

    final header = Container(
        padding: const EdgeInsets.all(24),
        color: Colors.blue,
        child: Text('Header'));

    final itemWidget = Padding(
        padding: const EdgeInsets.symmetric(vertical: 16), child: Text('item'));

    final button = Container(
      padding: EdgeInsets.only(top: 24),
      width: double.infinity,
      child: ElevatedButton(onPressed: () {}, child: Text('Save')),
    );

    return SafeArea(
        child: Container(
            constraints: BoxConstraints(
                maxHeight: MediaQuery.of(context).size.height * 0.80),
            padding: EdgeInsets.all(24),
            width: double.infinity,
            child: Column(mainAxisSize: MainAxisSize.min, children: [
              bottomSheetClosingLine,
              Expanded(
                  child: StickySideWidget.bottom( /// Custom widget
                body: CustomScrollView(slivers: [
                  SliverPinnedHeader(child: header),
                  SliverToBoxAdapter(
                      child: Column(
                    children: items.map((item) => itemWidget).toList(),
                  ))
                ]),
                side: button,
              ))
            ])));
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 18:40:56