Flutter开发中如何为分类组件添加选中变红的底部指示条
Flutter 导航栏选中红色指示条实现方案
方案1:使用内置TabBar组件(推荐,适配绝大多数场景)
Flutter官方提供的TabBar组件原生支持自定义选中指示条,无需额外手动处理选中状态和切换动画,是最便捷的实现方案。
- 使用步骤:
- 用
DefaultTabController包裹页面组件,指定分类总数 - 在
AppBar的bottom属性中配置TabBar,通过indicator相关属性调整指示条样式
- 用
示例代码如下:
// 完整示例代码 import 'package:flutter/material.dart'; class CategoryNavPage extends StatelessWidget { const CategoryNavPage({super.key}); @override Widget build(BuildContext context) { return DefaultTabController( length: 3, // 替换为你的实际分类数量 child: Scaffold( appBar: AppBar( backgroundColor: Colors.white, elevation: 0, title: const Text('页面标题'), bottom: TabBar( // 选中文字样式 labelColor: Colors.red, labelStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500), // 未选中文字样式 unselectedLabelColor: Colors.black87, unselectedLabelStyle: const TextStyle(fontSize: 16), // 指示条配置 indicatorColor: Colors.red, indicatorWeight: 3, // 指示条高度 // 指示条宽度适配:label和文字同宽,tab和整个分类项同宽 indicatorSize: TabBarIndicatorSize.label, tabs: const [ Tab(text: '推荐'), Tab(text: '热门'), Tab(text: '最新'), ], ), ), // 分类对应的页面内容 body: const TabBarView( children: [ Center(child: Text('推荐页面内容')), Center(child: Text('热门页面内容')), Center(child: Text('最新页面内容')), ], ), ), ); } }
方案2:完全自定义导航栏(适配特殊定制需求)
如果你不需要TabBar和TabBarView的联动逻辑,或者有特殊的导航栏样式需求,可以手动实现导航栏:
- 实现思路:
- 维护一个
int类型的变量记录当前选中的分类索引 - 遍历生成所有分类项,每个分类项下方根据是否选中控制指示条的颜色
- 点击分类时更新选中索引,触发UI刷新
- 维护一个
示例代码如下:
import 'package:flutter/material.dart'; class CustomNavPage extends StatefulWidget { const CustomNavPage({super.key}); @override State<CustomNavPage> createState() => _CustomNavPageState(); } class _CustomNavPageState extends State<CustomNavPage> { // 记录当前选中的索引 int _currentIndex = 0; // 分类列表,替换为你的实际分类 final List<String> _categories = ['推荐', '热门', '最新']; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, appBar: AppBar( backgroundColor: Colors.white, elevation: 0, title: const Text('页面标题'), // 自定义导航栏放在title下方,或者直接替换title bottom: PreferredSize( preferredSize: const Size.fromHeight(48), child: Row( children: _categories.asMap().entries.map((entry) { final index = entry.key; final title = entry.value; final isSelected = index == _currentIndex; return GestureDetector( onTap: () { setState(() { _currentIndex = index; }); // 此处添加点击分类后的业务逻辑 }, child: Container( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( title, style: TextStyle( color: isSelected ? Colors.red : Colors.black87, fontSize: 16, fontWeight: isSelected ? FontWeight.w500 : FontWeight.normal, ), ), const SizedBox(height: 6), // 选中指示条,AnimatedContainer自带切换动画 AnimatedContainer( duration: const Duration(milliseconds: 200), height: 3, width: 24, color: isSelected ? Colors.red : Colors.transparent, ) ], ), ), ); }).toList(), ), ), ), body: const Center(child: Text('页面内容')), ); } }
内容的提问来源于stack exchange,提问作者Mohamad Jabaly
相关产品推荐
相关产品推荐

