在手机上,tabbar是很常见的导航方式,在flutter中我们通过TabBar、TabController和TabBarView轻松实现效果。
在flutter中,我们如何通过代码控制选项卡间的导航呢?
下面,我们通过以下例子来说明tabbar的功能:
我们首先使用StatefulWidget
创建TabBar。
// Just a standard StatefulWidget
class JobApplicationFlow extends StatefulWidget {
const JobApplicationFlow({Key? key}) : super(key: key);
@override
_JobApplicationFlowState createState() => _JobApplicationFlowState();
}
// This is where the interesting stuff happens
class _JobApplicationFlowState extends State<JobApplicationFlow>
with SingleTickerProviderStateMixin {
// We need a TabController to control the selected tab programmatically
late final _tabController = TabController(length: 3, vsync: this);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Job Application'),
// Use TabBar to show the three tabs
bottom: TabBar(
controller: _tabController,
tabs: const <Widget>[
Tab(
icon: Icon(Icons.radio_button_on, color: Colors.white),
text: 'Experience',
),
Tab(
icon: Icon(Icons.check_box, color: Colors.white),
text: 'Skills',
),
Tab(
icon: Icon(Icons.send, color: Colors.white),
text: 'Submit',
),
],
),
),
);
}
}
接下来,添加TabBarView
用来显示所有的选项卡内容:
Scaffold(
appBar: AppBar(...),
body: TabBarView(
controller: _tabController,
children: [
ExperiencePage(
onNext: () => _tabController.index = 1,
),
SkillsPage(
onNext: () => _tabController.index = 2,
),
SubmitPage(
onSubmit: () => showCupertinoDialog(...),
),
],
),
)
在上面的代码中,每个页面都是一个自定义Widget,其中包含对应tab要展示的内容和一个触发onNext
oronSubmit
回调的按钮。
为了解决这个问题,我们可以创建一个ReadOnlyTabBar
用IgnorePointer
忽略与选项卡的所有交互:
// https://stackoverflow.com/a/57354375/436422
class ReadOnlyTabBar extends StatelessWidget implements PreferredSizeWidget {
final TabBar child;
const ReadOnlyTabBar({Key? key, required this.child}) : super(key: key);
@override
Widget build(BuildContext context) {
return IgnorePointer(child: child);
}
@override
Size get preferredSize => child.preferredSize;
}
然后,我们需要更新JobApplicationFlow
,让TabBar
成为ReadOnlyTabBar的child。
AppBar(
bottom: ReadOnlyTabBar(child:
TabBar(...),
),
)
除了tabBar的点击事件外,我们还要保证TabBarView的手势也不能使用,可以使用NeverScrollableScrollPhysics
实现该功能:
TabBarView(
// make sure we can't switch tabs with interactive drag gestures
physics: const NeverScrollableScrollPhysics(),
controller: _tabController,
children: [...],
)
最后,提交的时候,我们再加一个提示框,就达到我们想要的效果了。
SubmitPage(
onSubmit: () => showCupertinoDialog(
context: context,
builder: (_) {
return CupertinoAlertDialog(
title: const Text('Thank you'),
content: const Text('Your application was submitted.'),
actions: [
CupertinoDialogAction(
child: const Text('OK'),
onPressed: () {
// dismiss dialog
Navigator.of(context).pop();
_tabController.index = 0;
},
),
],
);
},
)
)
最终的效果:
codePen上的在线实例:https://dartpad.dev/?null_safety=true&id=aabd31bb2b9a4b16d822759fce8b5010
Happy Coding!
少年别走,交个朋友~