如何在Flutter中实现Android 12胶囊形状App Bar?
Flutter 实现 Android 12 胶囊形 AppBar 方案
完全可以实现和Play Store、系统信息/电话等谷歌系应用一致的胶囊形AppBar效果,不需要写原生桥接代码,用Flutter现有组件组合就能完成。

核心实现逻辑
这个效果本质是滚动联动的形态切换:页面初始状态AppBar是全宽贴合顶部的常规样式,随着页面向上滚动,AppBar逐步收缩成左右留边的悬浮胶囊形态,过程中搭配圆角、阴影、边距的平滑过渡,部分应用还会在胶囊状态加磨砂玻璃质感。
两种落地方式
1. 基于官方组件定制(可控性最高,无额外依赖)
直接改造官方SliverAppBar组件即可,步骤如下:
- 用
NotificationListener<ScrollNotification>监听列表滚动偏移,设置30dp左右的收缩阈值 - 偏移量未到阈值时:AppBar保持全宽,圆角为0,无悬浮阴影,和顶部完全贴合
- 偏移量达到/超过阈值时:给AppBar加上16dp左右的左右外边距、8dp上下外边距,形状设置为Flutter内置的
StadiumBorder()(原生胶囊形状),同时加上适当海拔阴影,需要磨砂效果就嵌套BackdropFilter做高斯模糊 - 所有属性变化用隐式动画(比如
AnimatedContainer、AnimatedPadding)做150-200ms的平滑过渡,不要直接硬切状态,避免突兀
核心实现代码片段:
double _scrollPixels = 0; final double _collapseThreshold = 30; @override Widget build(BuildContext context) { final bool isCollapsed = _scrollPixels >= _collapseThreshold; return Scaffold( body: NotificationListener<ScrollNotification>( onNotification: (scrollInfo) { setState(() { _scrollPixels = scrollInfo.metrics.pixels.clamp(0, _collapseThreshold); }); return false; }, child: CustomScrollView( slivers: [ SliverAnimatedPadding( duration: const Duration(milliseconds: 180), padding: EdgeInsets.symmetric( horizontal: isCollapsed ? 16 : 0, vertical: isCollapsed ? 8 : 0 ), sliver: SliverAppBar( shape: isCollapsed ? const StadiumBorder() : const RoundedRectangleBorder(), floating: true, pinned: true, elevation: isCollapsed ? 2 : 0, title: const Text("搜索内容"), actions: [ IconButton(onPressed: (){}, icon: const Icon(Icons.more_vert)) ], ), ), // 其余页面滚动内容放在下方 ], ), ) ); }
2. 用封装好的组件快速搭建
如果不想自己写滚动联动逻辑,可以直接用pub生态中已经封装好的Material You风格搜索栏/悬浮AppBar组件,比如material_floating_search_bar_2,这类组件已经内置了滚动收缩、胶囊形态、展开动效,简单配置参数就能对齐原生交互,适合快速迭代的业务场景。
效果对齐注意点
- 胶囊状态下AppBar高度保持和常规AppBar一致的56dp即可,不要随意改高度导致和原生观感不符
- 安卓12及以上设备可以配合动态取色能力,让AppBar颜色跟随系统壁纸主题变化,还原度更高
- 过渡动画时长不要超过200ms,和安卓系统动效速度保持一致,避免拖沓感
内容的提问来源于stack exchange,提问作者Arbër
相关产品推荐
相关产品推荐

