Flutter如何在Sliver列表非底部插入占剩余空间的可滚动列表
解决方案
核心布局逻辑
要实现按钮固定底部、上方滚动区域占满剩余空间的需求,不需要在CustomScrollView内部处理底部按钮,直接调整页面基础布局结构即可:
- 将Scaffold的body改为
Column组件,分为两个层级:上方可滚动区域、底部固定按钮栏 - 用
Expanded包裹原来的CustomScrollView,让其自动占用Column除底部按钮之外的所有剩余高度 - 将底部操作按钮从CustomScrollView的slivers列表中移出,作为Column的最后一个子组件,实现固定不滚动的效果
修改后的完整代码
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return MaterialApp( title: 'Slivers Headache', home: Scaffold( resizeToAvoidBottomInset: true, // 改用Column作为根布局,拆分滚动区域和固定按钮 body: Column( children: [ // Expanded给CustomScrollView明确可用高度,避免边界报错 Expanded( child: CustomScrollView( slivers: <Widget>[ const SliverAppBar( primary: true, flexibleSpace: FlexibleSpaceBar(title: Text('Slivers')) ), SliverToBoxAdapter( child: TextField( controller: TextEditingController(text: 'Text1'), onChanged: (value) => {}, decoration: const InputDecoration(border: OutlineInputBorder()), ) ), SliverToBoxAdapter( child: TextField( controller: TextEditingController(text: 'Text1'), onChanged: (value) => {}, decoration: const InputDecoration(border: OutlineInputBorder()), ) ), SliverToBoxAdapter( child: CheckboxListTile( tristate: false, title: const Text('checkbox'), value: false, onChanged: (bool? value) => {}, ) ), // 滚动列表无需额外包裹,自动适配可用高度 SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return ListTile( title: Text('Wish I could fill and scroll $index'), ); }, childCount: 30, // 可调整数值测试滚动效果 ) ), ] ), ), // 底部固定按钮栏,不参与滚动逻辑 Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextButton( child: const Text('Confirm'), onPressed: () { print('Confirmed'); Navigator.pop(context); } ), TextButton( child: const Text('Cancel'), onPressed: () { print('Cancelled'); Navigator.pop(context); } ) ] ) ], ) ) ); } }
关键说明
- 原代码将按钮放在CustomScrollView的slivers列表中,会跟随列表滚动,不符合固定底部的需求,移出后即可解决
- Expanded组件给CustomScrollView明确了可用的最大高度,内部滚动列表不会再出现无边界高度的RenderBox报错
- 你之前遇到的SliverFillRemaining只能放在slivers最底部的限制,是因为该组件作用是填充CustomScrollView内部的剩余空间,而你的需求是按钮固定在整个页面底部,不属于滚动内容,因此不需要使用该组件
内容的提问来源于stack exchange,提问作者byezy
相关产品推荐
相关产品推荐

