Flutter类Web布局:内容居中、页脚自适应定位的优雅实现
Flutter 自适应页脚布局实现方案
目标布局效果
- 内容高度不足以填满屏幕时,页脚固定贴合屏幕底部
- 内容高度超过屏幕时,页脚随内容流排布,仅滚动到页面最底部时才显示
- 内容高度不足以填满屏幕时,内容区需在AppBar与页脚之间垂直居中显示
原有方案问题
原有实现通过GlobalKey获取内容尺寸、帧回调后计算剩余空间、插入上下占位SizedBox的方式可以满足需求,但存在额外的setState开销,代码冗余,维护成本高。
优雅实现方案
无需运行时尺寸计算、无需回调监听,直接通过Flutter原生Sliver布局能力实现全部需求,完整代码如下:
Scaffold( body: Column( children: <Widget>[ // 固定高度AppBar const SizedBox( height: 100, child: MyAppBar(), ), // 内容+滚动区域占满AppBar以下全部可用空间 Expanded( child: CustomScrollView( slivers: [ SliverFillRemaining( hasScrollBody: false, child: Column( children: [ // 内容区:自动在可用空间内垂直居中 Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ // 替换为实际页面内容 Container(color: Colors.red, width: 300, height: 300), Container(color: Colors.green, width: 300, height: 300), Container(color: Colors.amber, width: 300, height: 300), ], ), ), // 固定高度页脚 const SizedBox( height: 150, child: MyFooter(), ), ], ), ), ], ), ), ], ), )
实现原理
SliverFillRemaining是Flutter提供的专门用于滚动视图剩余空间填充的组件,配合hasScrollBody: false参数,可以自动适配两种场景:- 内部内容总高度小于滚动视口高度时,自动撑满整个视口剩余空间
- 内部内容总高度大于滚动视口高度时,自动收缩到子组件的实际高度,跟随内容流排布
- 内部Column通过
Expanded包裹内容区,强制内容区占满SliverFillRemaining中除页脚外的全部高度,再给内容区设置mainAxisAlignment: MainAxisAlignment.center,自动实现内容垂直居中 - 页脚固定在Column底部,内容不足时因为SliverFillRemaining撑满视口,页脚自然贴合屏幕底部;内容超出时SliverFillRemaining收缩,页脚自然排在内容末尾,滚动到底部即可见
内容的提问来源于stack exchange,提问作者lucie
相关产品推荐
相关产品推荐

