TabBar
的实现方式不允许设置灵活的标签。因此,您必须计算每个标签的水平填充。
您需要获取制表符宽度,以便执行此操作:
- 为每个
GlobalKey
设置一个Tab
,然后访问
key.currentContext.size.width
。
- 由于
key.currentContext
在构建期间为null
,因此您需要
等待呈现TabBar
,然后获取制表符的宽度。去做
您可以使用WidgetsBinding.instance.addPostFrameCallback()
initState
内。
- 如果设备方向可以更改,则需要计算填充
再次,因此您可以在
didChangeDependencies
内而不是
initState
。
- 计算填充后,您需要将该填充存储在
变量,然后调用
setState
来更新标签的填充。
- 为避免在整个树中调用
setState
,您可以将
TabBar
自定义StatefulWidget
中。
- 要能够对应用中的任何
TabBar
执行此操作,可以创建一个
自定义TabBar
小部件,它接收TabBar
并返回一个新的
计算出的填充量。
因此,根据您的情况,您可以实现部分或全部提到的要点。这是一个提到所有要点的示例:
class TabBarWithFlexibleTabs extends StatefulWidget implements PreferredSizeWidget {
TabBarWithFlexibleTabs({this.child});
final TabBar child;
@override
Size get preferredSize => child.preferredSize;
@override
_TabBarWithFlexibleTabsState createState() => _TabBarWithFlexibleTabsState();
}
class _TabBarWithFlexibleTabsState extends State<TabBarWithFlexibleTabs> {
final _tabs = <Widget>[];
final _tabsKeys = <Tab,GlobalKey>{};
var _tabsPadding = 0.0;
void _updateTabBarPadding() => setState(() {
final screenWidth = MediaQuery.of(context).size.width;
final tabBarWidth = _tabsKeys.values
.fold(0,(prev,tab) => prev + tab.currentContext.size.width);
_tabsPadding = tabBarWidth < screenWidth
? ((screenWidth - tabBarWidth) / widget.child.tabs.length) / 2
: widget.child.labelPadding?.horizontal ?? 16.0;
});
@override
void initState() {
super.initState();
widget.child.tabs.forEach((tab) => _tabsKeys[tab] = GlobalKey());
_tabs.addAll(widget.child.tabs
.map((tab) => Container(key: _tabsKeys[tab],child: tab)));
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
WidgetsBinding.instance.addPostFrameCallback((_) => _updateTabBarPadding());
}
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: widget.child.tabs.length,child: TabBar(
tabs: _tabs,isScrollable: true,labelPadding: EdgeInsets.symmetric(
horizontal: _tabsPadding,vertical: widget.child.labelPadding?.vertical ?? 0,),// TODO: pass other parameters used in the TabBar received,like this:
controller: widget.child.controller,indicatorColor: widget.child.indicatorColor,);
}
}
您可以这样使用它:
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: TabBarWithFlexibleTabs(
child: TabBar(
tabs: <Widget>[
Tab(
text: 'General',Tab(
text: 'Financial',Tab(
text: 'Experts & Participants',],)
),);
}
注意:
-
TabBar
如果不适合屏幕宽度,将可以滚动。
- 检查
// TODO: pass other parameters used in the TabBar received
。
- 如果要使用
DefaultTabController
,则可能需要删除
自定义的。
本文链接:https://www.f2er.com/3136796.html