本教程将向您展示如何使用TabBar
和TabBarView
在 Flutter 中创建选项卡布局。
如果您的应用程序需要显示某些内容,将内容分成多个选项卡是很常见的。在 Flutter 中,借助TabBar
和TabBarView
小部件可以轻松创建这样的布局。TabBar
用于创建选项卡,而TabBarView
用于定义每个选项卡的内容。Flutter 已经处理了如何在选项卡之间切换,这对我们来说更容易。此外,Flutter 还可以自定义选项卡布局的样式和行为。下面是解释和例子。
基本用法
提供一个 TabController
TabBar
和TabBarView
需要一个TabController
工作。有两种不同的方式来提供控制器。第一个是将 aDefaultTabController
作为祖先小部件。DefaultTabController
可以使用下面的构造函数创建。
const DefaultTabController({
Key? key,
required int length,
int initialIndex = 0,
required Widget child,
})
复制代码
该length
参数用于设置您要创建的选项卡数量。它必须是相同的长度TabBar.tabs
和TabBarView.children
。否则,您可能会收到以下错误。
The following assertion was thrown building TabBar(dirty, dependencies: [_LocalizationsScope-[GlobalKey#7d8f8], _TabControllerScope, _InheritedTheme], state: _TabBarState#0360c):
Controller's length property (3) does not match the number of tabs (2) present in TabBar's tabs property.
复制代码
然后,您需要传递一个小部件作为child
参数。在TabBar
和TabBarView
小部件有(下面将被置为子控件的后代DefaultTabController
在树节点)。
MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
// Add Tabs here
],
),
title: const Text('坚果前端'),
backgroundColor: Colors.teal,
),
body: const TabBarView(
physics: BouncingScrollPhysics(),
dragStartBehavior: DragStartBehavior.down,
children: [
// Add widgets here
],
),
),
),
)
复制代码
提供一种控制器的另一种方式是通过使用controller
的参数TabBar
。它提供了更多的选择来控制TabBar
和TabBarView
的行为,与DefaultTabController
配合使用。例如,您可以以编程方式触发控制器为特定选项卡设置动画。
TabController({
int initialIndex = 0,
required int length,
required TickerProvider vsync
})
复制代码
要创建自己的TabController
,您必须传递length
指示选项卡数量的参数。它需要的值是和 TabBar.tabs和
TabBarView.children相同的长度。您必须传递的另一个必需参数是
vsync. 您可以通过添加
with TickerProviderStateMixin到您的
State类中来获取它,以便您可以使用
this关键字作为
vsync`参数的值。
class _TabLayoutExampleState extends State<TabLayoutExample> with TickerProviderStateMixin {
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 6, vsync: this);
_tabController.animateTo(2);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: _tabController,
tabs: [
// Put Tabs here
],
),
title: const Text('Woolha.com Flutter Tutorial'),
backgroundColor: Colors.teal,
),
body: TabBarView(
controller: _tabController,
children: [
// Put widgets here
],
),
),
);
}
}
复制代码
创建 TabBar
如果要实现选项卡布局,首先需要有一个包含选项卡列表的选项卡栏。在 Flutter 中,您可以使用TabBar
小部件。的TabBar
可以在任何地方根据设计被放置。如果你想把它放在 的正下方AppBar
,你可以将它作为 的bottom
参数传递AppBar
。下面是构造函数。
TabBar({
Key? key,
required List<Widget> tabs,
TabController? controller,
bool isScrollable,
Color? indicatorColor,
bool automaticIndicatorColorAdjustment,
double indicatorWeight,
EdgeInsetsGeometry indicatorPadding,
Decoration? indicator,
TabBarIndicatorSize? indicatorSize,
Color? labelColor,
TextStyle? labelStyle,
EdgeInsetsGeometry? labelPadding,
Color? unselectedLabelColor,
TextStyle? unselectedLabelStyle,
DragStartBehavior dragStartBehavior,
MaterialStateProperty<Color?>? overlayColor,
MouseCursor? mouseCursor,
bool? enableFeedback,
ValueChanged<int>? onTap,
ScrollPhysics? physics
})
复制代码
构造函数有很多参数,但大多数都是可选的。唯一需要的参数是tabs
您需要为其传递Tab
小部件列表。对于要显示的每个选项卡,您需要创建一个Tab
小部件。Tab
小部件的数量必须与TabController.length
和 的长度相同TabBarView.children
。
创建 Tab
要创建 的实例Tab
,您可以使用下面的构造函数。
const Tab({
Key? key,
String? text,
Widget? icon,
EdgeInsetsGeometry iconMargin = const EdgeInsets.only(bottom: 10.0),
Widget? child,
})
复制代码
FlutterTab
通过传递text
( String
)、icon
( Widget
) 或child
( Widget
) 参数中的至少一个,使您可以灵活地定义 。因此,您可以选择其中之一,也可以将它们组合起来,但是,不允许同时通过text
和child
。这意味着您只能传递text
only、icon
only、child
only、text
+icon
和icon
+ child
。
static const List<Tab> _tabs = [
const Tab(icon: Icon(Icons.looks_one), child: const Text('Tab One')),
const Tab(icon: Icon(Icons.looks_two), text: 'Tab Two'),
const Tab(icon: Icon(Icons.looks_3), text: 'Tab Three'),
];
复制代码
Tab
s 的列表需要作为 的tabs
参数传递TabBar
。
创建 TabBarView
除了TabBar
,您还需要使用下面的构造函数创建TabBarView
。
TabBarView({ Key? key, required List<Widget> children, TabController? controller, ScrollPhysics? physics, DragStartBehavior dragStartBehavior })
复制代码
对于Tab
作为 的tabs
参数传递的每个TabBar
,您需要定义其对应的视图。为此,您必须传递一个Widget
s 列表作为children
参数。传递的小部件的顺序必须与选项卡的顺序相同。
static const List<Widget> _views = [ const Center(child: const Text('Content of Tab One')), const Center(child: const Text('Content of Tab Two')), const Center(child: const Text('Content of Tab Three')), ];
复制代码
需要作为传递部件列表tabs
的说法TabBarView
。
TabBarView( children: _views, )
复制代码
正确创建TabBar
和后TabBarView
,您应该有一个有效的选项卡布局。
定制 TabBar
可选参数TabBar
可用于自定义TabBar
.
设置样式
您可以通过传递一个Color
值作为labelColor
参数来设置图标和文本的颜色。对于未选择的选项卡,您可以通过传递另一个Color
作为unselectedLabelColor
参数来为图标和文本设置不同的颜色。您还可以TextStyle
通过传递labelStyle
参数来设置。它还提供unselectedLabelStyle
可用于设置未选择选项卡的样式。对于设置颜色,您不能使用labelStyle
和unselectedLabelStyle
参数,即使TextStyle
可以使用 a 来定义颜色。为此,您必须使用labelColor
和unselectedLabelColor
参数。
TabBar( labelColor: Colors.red, unselectedLabelColor: Colors.grey, labelStyle: const TextStyle(fontWeight: FontWeight.bold), unselectedLabelStyle: const TextStyle(fontStyle: FontStyle.italic), tabs: _tabs, )
复制代码
输出:
仍然与颜色相关,Tab
小部件有一个参数overlayColor
,可用于定义选项卡处于聚焦、悬停和按下状态时的墨水颜色。您需要传递一个接受 aSet<MaterialState>
作为参数并Color
根据当前状态返回 的函数。
TabBar( labelColor: Colors.red, unselectedLabelColor: Colors.grey, labelStyle: const TextStyle(fontWeight: FontWeight.bold), unselectedLabelStyle: const TextStyle(fontStyle: FontStyle.italic), overlayColor: MaterialStateColor.resolveWith((Set<MaterialState> states) { if (states.contains(MaterialState.pressed)) { return Colors.blue; } if (states.contains(MaterialState.focused)) { return Colors.orange; } else if (states.contains(MaterialState.hovered)) { return Colors.pinkAccent; } return Colors.transparent; }), tabs: _tabs, )
复制代码
输出:
自定义指示器
在这种情况下,指示器是用于指示正在选择选项卡的布局的一部分。默认情况下,Flutter 会在所选选项卡的底部显示一个非常细的水平条。如果你想让它看起来更厚,你可以改变indicatorWeight
它的默认值为 2.0。可以通过传递 aColor
作为indicatorColor
参数来更改指示器颜色。
指示器另一种自定义是通过将TabBarIndicatorSize
枚举值作为indicatorSize
参数传递的大小。如果值为tab
,指标将与选项卡一样宽。如果值为label
,则指示器的宽度取决于标签的宽度。也可以使用indicatorPadding
类型为的参数在指标周围添加填充EdgeInsetsGeometry
。
TabBar( indicatorWeight: 10, indicatorColor: Colors.red, indicatorSize: TabBarIndicatorSize.tab, indicatorPadding: const EdgeInsets.all(10), tabs: _tabs, )
复制代码
输出:
如果您想为指示器使用完全不同的设计而不是选项卡底部的默认水平条,您可以将 Decoration
作为指示器参数传递。如果您创建自定义指示器,则indicatorColor
参数在传递后可能无效。
TabBar( indicatorPadding: const EdgeInsets.all(5), indicator: BoxDecoration( border: Border.all(color: Colors.red), borderRadius: BorderRadius.circular(10), color: Colors.pinkAccent, ), tabs: _tabs, )
复制代码
输出:
使标签可滚动
有时,选项卡可能很长并且不适合屏幕的宽度。默认情况下,Flutter 不会使其可滚动。结果,每个选项卡变得非常窄,某些部分被截断。该解决方案通过命名参数isScrollable
与true
作为值。
TabBar( isScrollable: true, tabs: _tabs, )
复制代码
输出:
设置 Physics
如果您使选项卡可滚动,您还可以设置用户滚动选项卡时的物理行为。为此,请传递一个ScrollPhysics
值作为physics
参数。下面的示例使用BouncingScrollPhysics
.
TabBar( isScrollable: true, physics: BouncingScrollPhysics(), tabs: _tabs, )
复制代码
输出:
选项卡上的 Handle
当一个选项卡被按下时,Flutter 会自动切换到相应的TabView
. 如果您想在按下选项卡时触发另一件事,您可以传递一个回调函数作为onTap
参数。
TabBar( onTap: (int index) { print('Tab $index is tapped'); }, tabs: _tabs, )
复制代码
启用反馈
要启用反馈,您可以传递enableFeedback
参数并将值设置为true
。
TabBar( enableFeedback: true, tabs: _tabs, )
复制代码
定制 TabBarView
TabBarView
的内容取决于您作为children
参数传递的小部件。因此,这取决于您如何创建小部件。除此之外,Flutter 还允许您自定义TabBarView
.
设置 Physics
您可以通过TabBarView
将physics
参数传递给 的构造函数来设置用户滚动 时的物理行为TabBarView
。传递的值必须是 ScrollPhysics
。下面的示例使用BouncingScrollPhysics
.
TabBarView( physics: BouncingScrollPhysics(), children: _views, )
复制代码
输出:
DefaultTabController
- 参数
Key? key
:小部件的键,用于控制小部件如何替换为另一个小部件。
required int length
:标签的数量。
int initialIndex
:所选标签的初始索引。默认为 0。
required Widget child
:树中此小部件下方的小部件,其中包含TabBar
和TabBarView
。
?: 值可以为空。required:必须传递值。
TabController
- 参数
required int length
:标签的数量。
int initialIndex
:所选标签的初始索引。默认为 0。
required TickerProvider vsync
:TickerProvider
使用。
required:必须传递值。
TabBar
- 参数
Key? key
:widget 的 key,用于控制 widget 被替换的方式
required List<Widget> tabs
:选项卡列表。
TabController? controller
:用于控制选择和动画状态。
bool isScrollable
: 这个标签栏是否可以水平滚动。默认为false
.
Color? indicatorColor
:所选选项卡下方线条的颜色。
bool automaticIndicatorColorAdjustment
:indicatorColor
如果与indicatorColor
父控件的颜色相同,此标签栏是否应自动调整为白色。默认为true
.
double indicatorWeight
:所选选项卡下方线条的粗细。默认为 2.0。
EdgeInsetsGeometry indicatorPadding
:指标的填充。默认为EdgeInsets.zero
.
Decoration? indicator
: 用于创建自定义指标。
TabBarIndicatorSize? indicatorSize
: 如何确定指标大小。
Color? labelColor
:所选标签标签的颜色。
TextStyle? labelStyle
:所选标签标签的文本样式。
EdgeInsetsGeometry? labelPadding
:添加到每个选项卡标签的填充。
Color? unselectedLabelColor
:未选中的标签标签的颜色。
Color? unselectedLabelStyle
:未选中的标签标签的文本样式。
DragStartBehavior dragStartBehavior
:确定处理拖动开始行为的方式。默认为DragStartBehavior.start
.
MaterialStateProperty<Color?>? overlayColor
:定义墨水响应焦点、悬停和飞溅颜色。
MouseCursor? mouseCursor
:当指针悬停在选项卡上时鼠标光标..
bool? enableFeedback
:手势是否应提供声音和/或触觉反馈。
ValueChanged<int>? onTap
:点击选项卡时调用的回调。
ScrollPhysics? physics
:当用户交互时影响胺化的物理效果。
?: 值可以为空。required:必须传递值。
TabBarView
- 参数
Key? key
:小部件的键,用于控制小部件如何替换为另一个小部件。
required List<Widget> children
:每个选项卡的小部件。
TabController? controller
:用于控制选择和动画状态。
ScrollPhysics? physics
:当用户交互时影响胺化的物理效果。
DragStartBehavior dragStartBehavior
:确定处理拖动开始行为的方式。默认为DragStartBehavior.start
.
?: 值可以为空。required:必须传递值。
完整代码
import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: '坚果前端', home: TabLayoutExample(), ); } } class TabLayoutExample extends StatefulWidget { @override State<StatefulWidget> createState() { return _TabLayoutExampleState(); } } class _TabLayoutExampleState extends State<TabLayoutExample> with TickerProviderStateMixin { late TabController _tabController; @override void initState() { super.initState(); _tabController = TabController(length: 6, vsync: this); _tabController.animateTo(2); } static const List<Tab> _tabs = [ const Tab(icon: Icon(Icons.looks_one), child: const Text('Tab One')), const Tab(icon: Icon(Icons.looks_two), text: 'Tab Two'), const Tab(icon: Icon(Icons.looks_3), text: 'Tab Three'), const Tab(icon: Icon(Icons.looks_4), text: 'Tab Four'), const Tab(icon: Icon(Icons.looks_5), text: 'Tab Five'), const Tab(icon: Icon(Icons.looks_6), text: 'Tab Six'), ]; static const List<Widget> _views = [ const Center(child: const Text('Content of Tab One')), const Center(child: const Text('Content of Tab Two')), const Center(child: const Text('Content of Tab Three')), const Center(child: const Text('Content of Tab Four')), const Center(child: const Text('Content of Tab Five')), const Center(child: const Text('Content of Tab Six')), ]; @override Widget build(BuildContext context) { return MaterialApp( home: DefaultTabController( length: 6, child: Scaffold( appBar: AppBar( bottom: TabBar( labelColor: Colors.white, unselectedLabelColor: Colors.grey, labelStyle: const TextStyle(fontWeight: FontWeight.bold), unselectedLabelStyle: const TextStyle(fontStyle: FontStyle.italic), overlayColor: MaterialStateColor.resolveWith((Set<MaterialState> states) { if (states.contains(MaterialState.pressed)) { return Colors.blue; } if (states.contains(MaterialState.focused)) { return Colors.orange; } else if (states.contains(MaterialState.hovered)) { return Colors.pinkAccent; } return Colors.transparent; }), indicatorWeight: 10, indicatorColor: Colors.red, indicatorSize: TabBarIndicatorSize.tab, indicatorPadding: const EdgeInsets.all(5), indicator: BoxDecoration( border: Border.all(color: Colors.red), borderRadius: BorderRadius.circular(10), color: Colors.pinkAccent, ), isScrollable: true, physics: BouncingScrollPhysics(), onTap: (int index) { print('Tab $index is tapped'); }, enableFeedback: true, // Uncomment the line below and remove DefaultTabController if you want to use a custom TabController // controller: _tabController, tabs: _tabs, ), title: const Text('Woolha.com Flutter Tutorial'), backgroundColor: Colors.teal, ), body: const TabBarView( physics: BouncingScrollPhysics(), // Uncomment the line below and remove DefaultTabController if you want to use a custom TabController // controller: _tabController, children: _views, ), ), ), ); } }
复制代码
概括
这就是在 Flutter 中创建选项卡布局的方法。首先,您需要有一个TabController
. 然后,您需要创建一个TabBar
包含选项卡列表的和一个TabBarView
包含每个选项卡的视图。可以通过传递可选参数来自定义选项卡的行为样式。
今天的内容到这儿就分享到这儿。不知道通过这种方式大家能否理解!
评论