Flutter中TabBar切换当前索引时如何实现选中项高度动态变化
问题原因
你当前的实现没有绑定Tab选中索引的状态监听,也没有根据动态变化的选中索引给所有Tab项统一应用样式规则,所以选中逻辑只能对固定索引起效,无法适配全量切换场景。
实现方案
核心思路是手动管控TabController实例,实时监听选中索引变化,通过状态驱动每个Tab项的尺寸渲染,加上动画组件实现平滑的放大聚焦效果,步骤如下:
- 手动初始化
TabController,添加索引变化监听,用状态变量记录当前选中的Tab索引 - 遍历生成所有Tab项,每个Tab项根据自身索引和当前选中索引的匹配状态,动态设置高度
- 用
AnimatedContainer包裹Tab内容,实现尺寸切换的过渡动画,避免生硬跳变 - 调整TabBar默认内边距配置,避免自定义尺寸的Tab出现布局溢出
完整可运行代码
import 'package:flutter/material.dart'; void main() { runApp(const MaterialApp(home: MyApp())); } class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> with TickerProviderStateMixin { late TabController _tabController; // 记录当前选中的Tab索引,默认选中第一个 int _selectedIndex = 0; @override void initState() { super.initState(); _tabController = TabController(length: 3, vsync: this); // 监听Tab切换事件 _tabController.addListener(() { if (_tabController.indexIsChanging) { setState(() { _selectedIndex = _tabController.index; }); } }); } @override void dispose() { _tabController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( backgroundColor: Colors.transparent, toolbarHeight: 120, bottom: TabBar( controller: _tabController, // 清除默认内边距,适配自定义Tab尺寸 labelPadding: EdgeInsets.zero, indicatorPadding: EdgeInsets.zero, indicator: BoxDecoration( border: Border.all(width: 1, color: Colors.deepOrange), borderRadius: BorderRadius.circular(10), color: Colors.transparent, ), // 动态生成3个Tab项 tabs: List.generate(3, (index) { return AnimatedContainer( duration: const Duration(milliseconds: 200), curve: Curves.easeInOut, // 选中项高度80,未选中项高度50,可自行调整尺寸差 height: _selectedIndex == index ? 80 : 50, padding: const EdgeInsets.symmetric(horizontal: 8), child: Card( child: Image( image: const AssetImage("assets/box.png"), fit: BoxFit.contain, ), ), ); }), ), ), body: TabBarView( controller: _tabController, children: const [ AmazonBox(), AmazonGift(), AmazonSave(), ], ), ), ); } } // 补全示例缺失的页面组件,实际使用替换为你的业务组件即可 class AmazonBox extends StatelessWidget { const AmazonBox({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const Center(child: Text("AmazonBox页面")); } } class AmazonGift extends StatelessWidget { const AmazonGift({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const Center(child: Text("AmazonGift页面")); } } class AmazonSave extends StatelessWidget { const AmazonSave({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return const Center(child: Text("AmazonSave页面")); } }
自定义调整说明
- 可以修改
AnimatedContainer的height参数差值,调整选中放大的幅度 - 可以修改
duration参数调整动画时长,替换curve参数调整动画插值效果 - 如果需要宽度也同步放大,可以给
AnimatedContainer加宽度变化的逻辑,或者直接用Transform.scale做整体缩放效果
内容的提问来源于stack exchange,提问作者Kumaresan Jackie
相关产品推荐
相关产品推荐

