fluent_ui
fluent_ui copied to clipboard
🐛 TabView does not keep state on reorder or tab change
Describe the bug When a Tab is clicked, the state of content in another tab in the same TabView resets to initial state
To Reproduce
import 'package:fluent_ui/fluent_ui.dart';
void main() {
runApp(const TestPage());
}
class TestPage extends StatefulWidget {
const TestPage({super.key});
@override
State<TestPage> createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
int currentIndex = 0;
@override
Widget build(BuildContext context) {
return FluentApp(
home: TabView(
currentIndex: currentIndex,
onChanged: (value) => setState(() {
currentIndex = value;
}),
tabs: [
Tab(text: const Text('test 1'), body: const CounterPage()),
Tab(text: const Text('test 2'), body: const CounterPage()),
Tab(text: const Text('test 3'), body: const CounterPage()),
],
),
);
}
}
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int counter = 0;
void increment(){
setState(() {
counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(children: [
Text('$counter'),
Button(onPressed: increment, child: const Text('increment'))
],);
}
}
Expected behavior When a Tab is clicked, the state of content in previous edited tab still the same
With some research, I found a workaround. Maybe it's good to incorporate to behavior of a TabView in this Lib.
Based on post from Diego Velasquez, at https://medium.com/@diegoveloper/flutter-persistent-tab-bars-a26220d322bc, Here it goes:
import 'package:fluent_ui/fluent_ui.dart';
void main() {
runApp(const TestPage());
}
class TestPage extends StatefulWidget {
const TestPage({super.key});
@override
State<TestPage> createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
int currentIndex = 0;
@override
Widget build(BuildContext context) {
return FluentApp(
home: TabView(
currentIndex: currentIndex,
onChanged: (value) => setState(() {
currentIndex = value;
}),
tabs: [
Tab(text: const Text('test 1'), body: const CounterPage()),
Tab(text: const Text('test 2'), body: const CounterPage()),
Tab(text: const Text('test 3'), body: const CounterPage()),
],
),
);
}
}
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> with AutomaticKeepAliveClientMixin<CounterPage> {
int counter = 0;
void increment(){
setState(() {
counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(children: [
Text('$counter'),
Button(onPressed: increment, child: const Text('increment'))
],);
}
@override
bool get wantKeepAlive => true;
}
just add the "AutomaticKeepAliveClientMixin" in the state of stateful widget and override the "wantKeepAlive" property to "true", boom! the magic it did.
Thanks in advance, the post from Diego Velasquez and the fluent_ui by itself is the most incredible thing that I see in flutter in the last years.
PS: I'm brazilian and my english maybe is not the best, forgive me by the prose, please.
TabView uses PageView under the hood, which doesn't support the automatic usage of KeepAlives, like list view or sliver lists do. It is up to the developer to add it, via AutomaticKeepAliveClientMixin, since adding it automatically including it can lead to several performance problems.
In case of usage of go_router, one can use StatefulShellRoute to keep the state of the routes. Another options are also available, such as page storage.