π TabView: RangeError (index): Invalid value: Not in inclusive range 0..1: 2
TENX-S opened this issue Β· comments
Ares Andrew commented
Describe the bug
An exception occurred when removing a tab:
βββ‘ EXCEPTION CAUGHT BY WIDGETS LIBRARY ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The following RangeError was thrown building:
RangeError (index): Invalid value: Not in inclusive range 0..2: 3
When the exception was thrown, this was the stack:
#0 List.[] (dart:core-patch/growable_array.dart:264:36)
#1 _TabViewState._tabBuilder (package:fluent_ui/src/controls/navigation/tab_view.dart:298:28)
#2 _TabViewState.build.<anonymous closure>.<anonymous closure>
(package:fluent_ui/src/controls/navigation/tab_view.dart:482:32)
#3 _ReorderableListViewState._itemBuilder (package:flutter/src/material/reorderable_list.dart:296:43)
#4 SliverReorderableListState._itemBuilder (package:flutter/src/widgets/reorderable_list.dart:958:44)
#5 SliverChildBuilderDelegate.build (package:flutter/src/widgets/scroll_delegate.dart:490:22)
#6 SliverMultiBoxAdaptorElement._build (package:flutter/src/widgets/sliver.dart:831:28)
#7 SliverMultiBoxAdaptorElement.performRebuild.processElement (package:flutter/src/widgets/sliver.dart:761:67)
#8 Iterable.forEach (dart:core/iterable.dart:347:35)
#9 SliverMultiBoxAdaptorElement.performRebuild (package:flutter/src/widgets/sliver.dart:808:24)
#10 SliverMultiBoxAdaptorElement.update (package:flutter/src/widgets/sliver.dart:737:7)
#11 Element.updateChild (package:flutter/src/widgets/framework.dart:3827:15)
#12 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:5512:16)
#13 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:5650:11)
#14 Element.rebuild (package:flutter/src/widgets/framework.dart:5203:7)
#15 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2905:19)
#16 WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:1021:21)
#17 RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:443:5)
#18 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1388:15)
#19 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1313:9)
#20 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1171:5)
#21 _invoke (dart:ui/hooks.dart:312:13)
#22 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:419:5)
#23 _drawFrame (dart:ui/hooks.dart:283:31)
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Screen.Recording.2024-03-08.at.10.46.02.mp4
Minimal reproducible code(from fluent_ui example):
import 'dart:math';
import 'package:fluent_ui/fluent_ui.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const App());
}
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return const FluentApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int currentIndex = 0;
List<Tab> tabs = [];
Tab generateTab(int index) {
late Tab tab;
tab = Tab(
text: Text('Document $index'),
semanticLabel: 'Document #$index',
icon: const FlutterLogo(),
body: Container(
color:
Colors.accentColors[Random().nextInt(Colors.accentColors.length)],
),
onClosed: () {
setState(() {
tabs.remove(tab);
if (currentIndex > 0) currentIndex--;
});
},
);
return tab;
}
@override
Widget build(BuildContext context) {
return NavigationView(
content: ScaffoldPage(
content: TabView(
tabs: tabs,
currentIndex: currentIndex,
onChanged: (index) => setState(() => currentIndex = index),
tabWidthBehavior: TabWidthBehavior.sizeToContent,
closeButtonVisibility: CloseButtonVisibilityMode.onHover,
showScrollButtons: false,
onNewPressed: () {
setState(() {
final index = tabs.length + 1;
final tab = generateTab(index);
tabs.add(tab);
});
},
onReorder: (oldIndex, newIndex) {
setState(() {
if (oldIndex < newIndex) {
newIndex -= 1;
}
final item = tabs.removeAt(oldIndex);
tabs.insert(newIndex, item);
if (currentIndex == newIndex) {
currentIndex = oldIndex;
} else if (currentIndex == oldIndex) {
currentIndex = newIndex;
}
});
},
),
),
);
}
}
Ares Andrew commented
Replace onClosed
with the following works:
onClosed: () {
tabs.remove(tab);
setState(() {
if (currentIndex > 0) currentIndex--;
});
},