如何让Flutter中SliverAppBar的leading与actions组件始终垂直居中?
问题根源在于:SliverAppBar的leading和actions区域默认绑定了标准工具栏高度(kToolbarHeight),和你设置的expandedHeight无关。展开时,按钮只会在固定高度的Toolbar区域内布局,自然无法对齐整个AppBar的垂直中心。
下面是两种可行的解决方案:
方案一:自定义leading/actions的高度容器
通过让leading和actions内的组件占满SliverAppBar的可用高度,再实现居中,同时保留默认的边距避免贴边:
SliverAppBar( pinned: MediaQuery.of(context).size.height > 900 ? true : false, snap: true, floating: true, expandedHeight: 80.0, stretchTriggerOffset: 300.0, flexibleSpace: FlexibleSpaceBar( title: Text('app title', style: Theme.of(context).textTheme.displayLarge!.copyWith(color: Colors.white)), centerTitle: true, background: Image.asset( 'assets/images/star-background.png', fit: BoxFit.cover, ), ), leading: Padding( padding: const EdgeInsets.only(left: 16), // 匹配默认leading边距 child: SizedBox( height: double.infinity, // 占满AppBar高度 child: Center( child: IconButton( icon: Icon(Icons.menu), onPressed: () => Scaffold.of(context).openDrawer(), ), ), ), ), actions: <Widget>[ Padding( padding: const EdgeInsets.only(right: 16), // 匹配默认actions边距 child: SizedBox( height: double.infinity, // 占满AppBar高度 child: Center( child: !userController.isLoggedIn() ? IconButton( icon: const Icon(Icons.login), tooltip: 'Log in', onPressed: () => Get.toNamed(AppLinks.LOGIN), ) : IconButton( icon: const Icon(Icons.bookmark), tooltip: 'Saved documents', onPressed: () => Get.toNamed(AppLinks.SAVED), ), ), ), ), ], )
方案二:将按钮整合到FlexibleSpaceBar的布局中
放弃使用SliverAppBar自带的leading和actions参数,直接在FlexibleSpaceBar的background里用Stack布局按钮,完全控制按钮在整个expandedHeight范围内的位置:
SliverAppBar( pinned: MediaQuery.of(context).size.height > 900 ? true : false, snap: true, floating: true, expandedHeight: 80.0, stretchTriggerOffset: 300.0, flexibleSpace: FlexibleSpaceBar( title: Text('app title', style: Theme.of(context).textTheme.displayLarge!.copyWith(color: Colors.white)), centerTitle: true, background: Stack( fit: StackFit.expand, children: [ // 背景图 Image.asset( 'assets/images/star-background.png', fit: BoxFit.cover, ), // 左侧菜单按钮 Positioned( left: 16, top: 0, bottom: 0, child: Center( child: IconButton( icon: Icon(Icons.menu), color: Colors.white, onPressed: () => Scaffold.of(context).openDrawer(), ), ), ), // 右侧操作按钮 Positioned( right: 16, top: 0, bottom: 0, child: Center( child: !userController.isLoggedIn() ? IconButton( icon: const Icon(Icons.login), color: Colors.white, tooltip: 'Log in', onPressed: () => Get.toNamed(AppLinks.LOGIN), ) : IconButton( icon: const Icon(Icons.bookmark), color: Colors.white, tooltip: 'Saved documents', onPressed: () => Get.toNamed(AppLinks.SAVED), ), ), ), ], ), ), )
为什么之前的方法无效?
你之前用Align/Center包裹按钮时,父容器是SliverAppBar内置的Toolbar区域,高度固定为kToolbarHeight(默认56),而非你设置的expandedHeight。所以居中仅作用于这个小区域,无法对齐整个AppBar的垂直中心。
内容的提问来源于stack exchange,提问作者djoll
相关产品推荐
相关产品推荐

