我试图在TabBar中动态添加和删除制表符,但是当添加选项卡会抛出异常时,它通常会工作。我想我做错了什么,但是并不明显--如果标签是静态定义的,一切都很好,当动态添加时,我执行以下两个步骤:
触发UI更新
该选项卡是可视化的,但是在控制台中有下面的例外:
═══════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown building TabBar(dirty, dependencies: [_LocalizationsScope-[GlobalKey#f57c6], _TabControllerScope, _InheritedTheme, Directionality], state: _TabBarState#cf630):
Controller's length property (4) does not match the number of tabs (3) present in TabBar's tabs property.
The relevant error-causing widget was
TabBar
lib\main.dart:317
When the exception was thrown, this was the stack
#0 _TabBarState.build.<anonymous closure>
package:flutter/…/material/tabs.dart:1159
#1 _TabBarState.build
package:flutter/…/material/tabs.dart:1165
#2 StatefulElement.build
package:flutter/…/widgets/framework.dart:4919
#3 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4806
#4 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:4977
#5 Element.rebuild
package:flutter/…/widgets/framework.dart:4529
#6 BuildOwner.buildScope
package:flutter/…/widgets/framework.dart:2659
#7 WidgetsBinding.drawFrame
package:flutter/…/widgets/binding.dart:891
#8 RendererBinding._handlePersistentFrameCallback
package:flutter/…/rendering/binding.dart:370
#9 SchedulerBinding._invokeFrameCallback
package:flutter/…/scheduler/binding.dart:1146
#10 SchedulerBinding.handleDrawFrame
package:flutter/…/scheduler/binding.dart:1083
#11 SchedulerBinding._handleDrawFrame
package:flutter/…/scheduler/binding.dart:997
#15 _invoke (dart:ui/hooks.dart:151:10)
#16 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:308:5)
#17 _drawFrame (dart:ui/hooks.dart:115:31)
(elided 3 frames from dart:async)
════════════════════════════════════════════════════════════════════════════════下面是代码的简化版本:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class TabsConfig {
static List<String> tabs = [];
static int selectedTabIndex = 0;
}
class MyApp extends MaterialApp {
MyApp({Key? key})
: super(
key: key,
home: const MainWidget(),
);
}
class MainWidget extends StatefulWidget {
const MainWidget({Key? key}) : super(key: key);
@override
State<MainWidget> createState() => MainWidgetState();
}
class MainWidgetState extends State<MainWidget>
with SingleTickerProviderStateMixin {
void updateTabs() {
try {
setState(() {});
} catch (on) {
print(on); // TODO: rem
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: DefaultTabController(
length: TabsConfig.tabs.length,
initialIndex: TabsConfig.selectedTabIndex,
child: CustomScrollView(
slivers: <Widget>[
getSliverTabBar(),
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
TabsConfig.tabs.add('New tab');
updateTabs();
},
),
);
}
Widget getSliverTabBar() {
print('tabs: ${TabsConfig.tabs.length}'); //TODO: rem
return SliverAppBar(
pinned: true,
backgroundColor: Colors.blue,
title: Align(
alignment: AlignmentDirectional.topStart,
child: TabBar(
indicatorColor: Colors.white,
isScrollable: true,
onTap: ((int selected) {
TabsConfig.selectedTabIndex = selected;
}),
tabs: TabsConfig.tabs
.map(
(e) => Tab(text: e),
)
.toList(),
),
),
);
}
}有什么想法可以让它发挥作用,或者是什么原因?谢谢!
发布于 2022-08-22 18:59:20
要动态生成选项卡,您可能必须使用自定义控制器,使用TickerProviderStateMixin代替SingleTickerProver,并在更新屏幕时更新控制器。做了个演示,让你开始
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MainWidget(),
);
}
}
class TabsConfig {
static List<String> tabs = [];
static int selectedTabIndex = 0;
}
class MainWidget extends StatefulWidget {
const MainWidget({Key? key}) : super(key: key);
@override
State<MainWidget> createState() => MainWidgetState();
}
class MainWidgetState extends State<MainWidget> with TickerProviderStateMixin {
late TabController controller;
@override
void initState() {
// TODO: implement initState
controller = TabController(
length: TabsConfig.tabs.length,
vsync: this,
initialIndex: TabsConfig.selectedTabIndex,
);
super.initState();
}
void updateTabs() {
try {
controller = TabController(
length: TabsConfig.tabs.length,
vsync: this,
initialIndex: TabsConfig.selectedTabIndex,
);
setState(() {});
} catch (on) {
print(on); // TODO: rem
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
TabBar(
isScrollable: true,
controller: controller,
labelColor: Theme.of(context).primaryColor,
unselectedLabelColor: Theme.of(context).hintColor,
indicator: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Theme.of(context).primaryColor,
width: 2,
),
),
),
tabs: List.generate(
TabsConfig.tabs.length,
(index) => Text("${TabsConfig.tabs[index]}"),
),
),
Expanded(
child: TabBarView(
controller: controller,
children: List.generate(
TabsConfig.tabs.length,
(index) => Center(
child: Text("${TabsConfig.tabs[index]}"),
),
),
),
),
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
TabsConfig.tabs.add('New tab ${TabsConfig.tabs.length}');
// setState(() {});
updateTabs();
},
),
);
}
}https://stackoverflow.com/questions/73449029
复制相似问题