如何在Flutter中实现Spotify风格的AppBar切换按钮?
实现Spotify风格的AppBar切换按钮
你可以通过两种方式实现目标效果:自定义TabBar样式,或者完全手动实现切换组件,以下是具体方案:
方案一:自定义TabBar适配Spotify样式
原生TabBar可以实现该效果,只需要调整样式参数匹配Spotify的视觉风格:
class SpotifyTabDemo extends StatelessWidget { const SpotifyTabDemo({super.key}); @override Widget build(BuildContext context) { return DefaultTabController( length: 3, child: Scaffold( appBar: AppBar( backgroundColor: Colors.black, title: const Text("Spotify Clone"), // 用PreferredSize控制TabBar高度,避免AppBar被过度拉伸 bottom: PreferredSize( preferredSize: const Size.fromHeight(50), child: TabBar( // 自定义下划线样式:绿色、短宽、居中 indicator: const UnderlineTabIndicator( borderSide: BorderSide(color: Colors.green, width: 2), insets: EdgeInsets.symmetric(horizontal: 20), ), // 选中/未选中文字颜色 labelColor: Colors.white, unselectedLabelColor: Colors.grey, // 选中/未选中文字粗细 labelStyle: const TextStyle(fontWeight: FontWeight.bold), unselectedLabelStyle: const TextStyle(fontWeight: FontWeight.normal), tabs: const [ Tab(text: "全部"), Tab(text: "音乐"), Tab(text: "播客"), ], ), ), ), body: const TabBarView( children: [ Center(child: Text("全部内容页")), Center(child: Text("音乐内容页")), Center(child: Text("播客内容页")), ], ), ), ); } }
关键调整点:
- 通过
UnderlineTabIndicator自定义下划线的颜色、宽度和边距,还原Spotify的短下划线效果 - 配置
labelColor/unselectedLabelColor控制文字切换变色 - 用
PreferredSize固定TabBar高度,避免影响AppBar整体布局
方案二:手动实现完全自定义的切换组件
如果TabBar的样式限制满足不了需求,可以用Row+GestureDetector完全手动实现,灵活性更高:
class CustomSpotifyTabs extends StatefulWidget { const CustomSpotifyTabs({super.key}); @override State<CustomSpotifyTabs> createState() => _CustomSpotifyTabsState(); } class _CustomSpotifyTabsState extends State<CustomSpotifyTabs> { int _selectedTabIndex = 0; final List<String> _tabTitles = ["全部", "音乐", "播客"]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Colors.black, title: const Text("Spotify Clone"), actions: [ Expanded( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(_tabTitles.length, (index) { return GestureDetector( onTap: () { setState(() => _selectedTabIndex = index); // 配合PageView切换页面:_pageController.jumpToPage(index); }, child: Container( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( _tabTitles[index], style: TextStyle( color: _selectedTabIndex == index ? Colors.white : Colors.grey, fontWeight: _selectedTabIndex == index ? FontWeight.bold : FontWeight.normal, ), ), // 选中时显示下划线 if (_selectedTabIndex == index) Container( margin: const EdgeInsets.only(top: 6), height: 2, width: 30, color: Colors.green, ), ], ), ), ); }), ), ), ], ), body: PageView( onPageChanged: (index) => setState(() => _selectedTabIndex = index), children: const [ Center(child: Text("全部内容页")), Center(child: Text("音乐内容页")), Center(child: Text("播客内容页")), ], ), ); } }
这种方式可以完全控制每个按钮的布局、间距、下划线样式,适合需要高度定制的场景。
内容的提问来源于stack exchange,提问作者user23665140
相关产品推荐
相关产品推荐

