英文:
When using TabBar in Flutter, how can I set the tab to change or not according to my own constraints?
问题
When using TabBar in Flutter, how can I set the tab to change or not according to my own constraints?
For example:
bool tabChangeable() {
return _formKey.currentState!.validate();
}
When the index changed, I went back to the old index and made my checks and changed the index again according to the current situation. However, when this method is applied, it enters an infinite loop because of the _tabController.animateTo(previousIndex)
code.
_tabController.addListener(() {
if (_tabController.indexIsChanging) {
int newIndex = _tabController.index;
int previousIndex = _tabController.previousIndex;
_tabController.animateTo(previousIndex);
if (_formKey.currentState!.validate()) {
_tabController.animateTo(newIndex);
}
}
});
I can't use a TabView because my height value is not fixed. I use the widget below instead.
class _LayoutBody extends StatefulWidget {
const _LayoutBody({
Key? key,
required this.tabController,
required this.tabChildren,
}) : super(key: key);
final TabController tabController;
final List<Widget> tabChildren;
@override
State<_LayoutBody> createState() => _LayoutBodyState();
}
class _LayoutBodyState extends State<_LayoutBody> {
@override
void initState() {
super.initState();
widget.tabController.addListener(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return widget.tabChildren[widget.tabController.index];
}
}
If there is TabView usage for different heights, I would appreciate it if you could write it down. Thanks everyone.
英文:
When using TabBar in Flutter, how can I set the tab to change or not according to my own constraints?
For example:
bool tabChangeable() {
return _formKey.currentState!.validate();
}
When the index changed, I went back to the old index and made my checks and changed the index again according to the current situation. However, when this method is applied, it enters an infinite loop because of the _tabController.animateTo(previousIndex)
code.
_tabController.addListener(() {
if (_tabController.indexIsChanging) {
int newIndex = _tabController.index;
int previousIndex = _tabController.previousIndex;
_tabController.animateTo(previousIndex);
if (_formKey.currentState!.validate()) {
_tabController.animateTo(newIndex);
}
}
});
--- Edit
I can't use a TabView because my height value is not fixed. I use the widget below instead.
class _LayoutBody extends StatefulWidget {
const _LayoutBody({
Key? key,
required this.tabController,
required this.tabChildren,
}) : super(key: key);
final TabController tabController;
final List<Widget> tabChildren;
@override
State<_LayoutBody> createState() => _LayoutBodyState();
}
class _LayoutBodyState extends State<_LayoutBody> {
@override
void initState() {
super.initState();
widget.tabController.addListener(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return widget.tabChildren[widget.tabController.index];
}
}
If there is TabView usage for different heights, I would appreciate it if you could write it down. Thanks everyone
答案1
得分: 0
Flirty setting physics: const NeverScrollableScrollPhysics(),
to disable the swap changes(mostly needed). Then use the TabController to change the tab only on validation, Here is a demo example
class FTExample extends StatefulWidget {
const FTExample({super.key});
@override
State<FTExample> createState() => _FTExampleState();
}
class _FTExampleState extends State<FTExample>
with SingleTickerProviderStateMixin {
final formKey = GlobalKey<FormState>();
late final tabController = TabController(length: 3, vsync: this);
@override
Widget build(BuildContext context) {
// tabbar
return Scaffold(
appBar: AppBar(
title: const Text('TabBar'),
),
body: Column(
children: [
TabBar(
controller: tabController,
tabs: [
Tab(
icon: Icon(Icons.directions_car),
),
Tab(
icon: Icon(Icons.directions_transit),
),
Tab(
icon: Icon(Icons.directions_bike),
),
],
),
Expanded(
child: TabBarView(
physics: const NeverScrollableScrollPhysics(), // 用这个设置禁用切换效果(通常需要)
controller: tabController,
children: [
//Form with a TextFiled and button
Form(
key: formKey,
child: Column(
children: [
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
decoration: InputDecoration(
labelText: 'Name',
hintText: 'Enter your name',
),
),
ElevatedButton(
onPressed: () {
if (formKey.currentState?.validate() == true) {
tabController.animateTo(1);
}
},
child: Text('Submit'),
),
],
),
),
Container(
color: Colors.green,
),
Container(
color: Colors.blue,
),
],
),
),
],
),
);
}
}
英文:
Flirty setting physics: const NeverScrollableScrollPhysics(),
to disable the swap changes(mostly needed).
Then use the TabController to change the tab only on validation, Here is a demo example
class FTExample extends StatefulWidget {
const FTExample({super.key});
@override
State<FTExample> createState() => _FTExampleState();
}
class _FTExampleState extends State<FTExample>
with SingleTickerProviderStateMixin {
final formKey = GlobalKey<FormState>();
late final tabController = TabController(length: 3, vsync: this);
@override
Widget build(BuildContext context) {
// tabbar
return Scaffold(
appBar: AppBar(
title: const Text('TabBar'),
),
body: Column(
children: [
TabBar(
controller: tabController,
tabs: [
Tab(
icon: Icon(Icons.directions_car),
),
Tab(
icon: Icon(Icons.directions_transit),
),
Tab(
icon: Icon(Icons.directions_bike),
),
],
),
Expanded(
child: TabBarView(
physics: const NeverScrollableScrollPhysics(), // you can use a bool to switch between NeverScrollableScrollPhysics and BouncingScrollPhysics
controller: tabController,
children: [
//Form with a TextFiled and button
Form(
key: formKey,
child: Column(
children: [
TextFormField(
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter some text';
}
return null;
},
decoration: InputDecoration(
labelText: 'Name',
hintText: 'Enter your name',
),
),
ElevatedButton(
onPressed: () {
if (formKey.currentState?.validate() == true) {
tabController.animateTo(1);
}
},
child: Text('Submit'),
),
],
),
),
Container(
color: Colors.green,
),
Container(
color: Colors.blue,
),
],
),
),
],
),
);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论