如何在showModalBottomSheet中使用DraggableScrollableSheet并固定顶部栏
解决思路
要实现拖拽底部弹窗时标题栏固定不跟随滚动,只需要把固定标题栏和可拖拽滚动的内容区做层级拆分即可,核心结构如下:
- 最外层用
Column作为弹窗根布局 - 第一层直接放你需要的固定标题栏(AppBar或者自定义Container都可以)
- 第二层用
Expanded包裹DraggableScrollableSheet,内部放你的可滚动内容(SingleChildScrollView/ListView)
这样拆分后标题栏会固定在弹窗顶部,只有下方内容区会跟随拖拽动作上下滚动。
修正后完整代码
bottomsheet(context) { Size size = MediaQuery.of(context).size; return showModalBottomSheet( backgroundColor: Colors.white, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(13)), ), context: context, // 重点:开启isScrollControlled让弹窗支持撑满高度 isScrollControlled: true, builder: (BuildContext context) { return Padding( padding: const EdgeInsets.all(5), child: Column( mainAxisSize: MainAxisSize.min, children: [ // 固定标题栏,不会跟随滚动 AppBar( foregroundColor: Colors.green, backgroundColor: Colors.white, elevation: 1, shadowColor: Colors.grey.shade100, automaticallyImplyLeading: false, title: const Text('Connect with Reconnect'), ), // 可拖拽滚动的内容区 Expanded( child: DraggableScrollableSheet( initialChildSize: 0.5, // 初始展示高度占父容器比例,可自行调整 minChildSize: 0.3, // 最小高度比例,可自行调整 maxChildSize: 0.9, // 最大高度比例,可自行调整 builder: (context, scrollController) { return SingleChildScrollView( // 必须绑定DraggableScrollableSheet提供的scrollController,避免滚动冲突 controller: scrollController, child: Padding( padding: const EdgeInsets.all(25), child: Container( padding: const EdgeInsets.only( left: 15, right: 15, top: 15, ), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(13), boxShadow: const [ BoxShadow(blurRadius: 2, color: Colors.grey), ], ), child: Column(children: [ TextField( cursorColor: Colors.green, decoration: InputDecoration( label: const Text('Name'), labelStyle: TextStyle(color: Colors.grey.shade500), icon: const Icon( Icons.person, color: Color(0xff453e3d), size: 22, ), border: InputBorder.none, ), ), Container( width: 315, height: 1, margin: const EdgeInsets.only(top: 3, bottom: 3), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(100), ), ), TextField( cursorColor: Colors.green, decoration: InputDecoration( label: const Text('Email'), labelStyle: TextStyle(color: Colors.grey.shade500), icon: const Icon( Icons.email, color: Color(0xff453e3d), size: 22, ), border: InputBorder.none, ), ), Container( width: 315, height: 1, margin: const EdgeInsets.only(top: 3, bottom: 3), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(100), ), ), TextField( cursorColor: Colors.green, decoration: InputDecoration( label: const Text('Phone Number'), labelStyle: TextStyle(color: Colors.grey.shade500), icon: const Icon( Icons.phone_android, color: Color(0xff453e3d), size: 22, ), border: InputBorder.none, ), ), Container( width: 315, height: 1, margin: const EdgeInsets.only(top: 3, bottom: 3), decoration: BoxDecoration( color: Colors.grey[300], borderRadius: BorderRadius.circular(100), ), ), Container( margin: const EdgeInsets.only(top: 10), height: 25, alignment: Alignment.bottomLeft, child: Row( children: [ const Icon( Icons.directions_car, color: Color(0xff453e3d), ), const SizedBox( width: 15, ), Text( 'Services', style: TextStyle( color: Colors.grey.shade500, fontSize: 16), ), ], ), ), ]), ), ), ); }, ), ) ], ), ); }); }
内容的提问来源于stack exchange,提问作者Suramack
相关产品推荐
相关产品推荐

