📅  最后修改于: 2023-12-03 14:52:17.463000             🧑  作者: Mango
在 Flutter 中使用 Tabs 是非常方便和常见的,但是默认的指示器可能不符合你的需求。本文将介绍如何在 Flutter Tabs 中添加圆点作为指示器。
在开始之前,您需要先准备好一个带有 Tabs 的页面,例如:
class MyTabs extends StatefulWidget {
@override
_MyTabsState createState() => _MyTabsState();
}
class _MyTabsState extends State<MyTabs> with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: _tabController,
tabs: [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
Tab(text: 'Tab 3'),
],
),
),
body: TabBarView(
controller: _tabController,
children: [
Container(color: Colors.red),
Container(color: Colors.blue),
Container(color: Colors.yellow),
],
),
);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
}
要将圆点添加到 Tabs 中,首先需要掌握的是:
TabBar
的 indicator 属性可以接受一个 Widget,用于自定义指示器。TabBarView
的 onPageChanged 回调可以获取当前页面的索引。利用这两个属性,我们可以很方便地添加圆点指示器。具体步骤如下:
class DotIndicator extends Decoration {
@override
BoxPainter createBoxPainter([VoidCallback onChanged]) {
return _DotBoxPainter();
}
}
class _DotBoxPainter extends BoxPainter {
static const double _radius = 3;
static const double _dotSpacing = 5;
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
final size = configuration.size;
final paint = Paint()..color = Colors.white;
final center = offset + Offset(size.width/2, size.height/2);
final maxRadius = _radius * 2;
for (var i = 0; i < configuration.tabCount; i++) {
var currentRadius = _radius;
if (i == configuration.selectedIndex) {
currentRadius = maxRadius;
}
final dx = -(configuration.tabCount * _radius * 2 + (configuration.tabCount - 1) * _dotSpacing) / 2 + i * (currentRadius * 2 + _dotSpacing);
final offset = center.translate(dx, 0);
canvas.drawCircle(offset, currentRadius, paint);
}
}
}
上述代码的作用是定义了一个继承自 Decoration
的圆点装饰器,其中 _DotBoxPainter
控制圆点的绘制。圆点的直径为 6,圆点之间的间隔为 5。在显示时,将会在当前 Tab 下方显示一个更大的圆点。
bottom: TabBar(
controller: _tabController,
indicator: DotIndicator(),
tabs: [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
Tab(text: 'Tab 3'),
],
),
通过将 DotIndicator
作为 indicator 属性传递给 TabBar
,可以将圆点指示器添加到 Tabs 中。
body: TabBarView(
controller: _tabController,
children: [
Container(color: Colors.red),
Container(color: Colors.blue),
Container(color: Colors.yellow),
],
onPageChanged: (index) {
setState(() {
_tabController.index = index;
});
},
),
为了保证圆点指示器在滑动 Tabs 时能够正确地显示,我们监听了 TabBarView
的 onPageChanged
事件,并在事件处理函数中手动设置了 TabController
的 index 属性。这样,当滑动到新的 Tab 时,TabController
会自动更新当前选择的 Tab,圆点指示器也能同步更新。
完成以上步骤后,就可以在 Tabs 中添加圆点指示器了。效果如下:
通过本文,您已经掌握了如何在 Flutter Tabs 中添加圆点作为指示器的方法,希望对您有所帮助。完整代码如下:
class MyTabs extends StatefulWidget {
@override
_MyTabsState createState() => _MyTabsState();
}
class _MyTabsState extends State<MyTabs> with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: _tabController,
indicator: DotIndicator(),
tabs: [
Tab(text: 'Tab 1'),
Tab(text: 'Tab 2'),
Tab(text: 'Tab 3'),
],
),
),
body: TabBarView(
controller: _tabController,
children: [
Container(color: Colors.red),
Container(color: Colors.blue),
Container(color: Colors.yellow),
],
onPageChanged: (index) {
setState(() {
_tabController.index = index;
});
},
),
);
}
@override
void dispose() {
_tabController.dispose();
super.dispose();
}
}
class DotIndicator extends Decoration {
@override
BoxPainter createBoxPainter([VoidCallback onChanged]) {
return _DotBoxPainter();
}
}
class _DotBoxPainter extends BoxPainter {
static const double _radius = 3;
static const double _dotSpacing = 5;
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
final size = configuration.size;
final paint = Paint()..color = Colors.white;
final center = offset + Offset(size.width/2, size.height/2);
final maxRadius = _radius * 2;
for (var i = 0; i < configuration.tabCount; i++) {
var currentRadius = _radius;
if (i == configuration.selectedIndex) {
currentRadius = maxRadius;
}
final dx = -(configuration.tabCount * _radius * 2 + (configuration.tabCount - 1) * _dotSpacing) / 2 + i * (currentRadius * 2 + _dotSpacing);
final offset = center.translate(dx, 0);
canvas.drawCircle(offset, currentRadius, paint);
}
}
}