I want to make a "Settings" button in the actions area of the AppBar. I seem to have succeeded, but I can click on this empty container. I want to make it so that Settings is either in the Tab widget but next to the buttons (minimize, close) or is in the actions list, but it was possible to switch between the buttons in the AppBar as in Tab.
import 'widgets/custom_appbar.dart';
import 'package:flutter/material.dart';
import 'package:window_manager/window_manager.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'constants.dart';
import 'widgets/main_tab/connect_to_server.dart';
import 'widgets/main_tab/create_server.dart';
class CoopAndreasLauncher extends StatefulWidget {
const CoopAndreasLauncher({super.key});
@override
State<CoopAndreasLauncher> createState() => _CoopAndreasLauncherState();
}
class _CoopAndreasLauncherState extends State<CoopAndreasLauncher> with TickerProviderStateMixin {
final TextEditingController nicknameController = TextEditingController();
final TextEditingController ipPortController = TextEditingController();
int maxPlayers = 2;
String selectedLanguage = 'English';
late TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(initialIndex: 0, vsync: this, length: 3);
}
@override
void dispose() {
nicknameController.dispose();
ipPortController.dispose();
_tabController.dispose();
super.dispose();
}
late final List<IconButton> _actions = [
IconButton(
icon: const Icon(FontAwesomeIcons.gear),
iconSize: 20.0,
onPressed: () {
_tabController.animateTo(2); // this line goto tab with index 2
},
),
IconButton(
icon: const Icon(Icons.minimize),
iconSize: 20.0,
onPressed: () {
windowManager.minimize();
},
),
IconButton(
icon: const Icon(Icons.close),
iconSize: 20.0,
onPressed: () {
windowManager.close();
},
)
];
@override
Widget build(BuildContext context) {
return DefaultTabController(
initialIndex: _tabController.index,
length: _tabController.length,
child: Scaffold(
appBar: CustomAppBar(
actions: _actions,
title: TabBar(
labelColor: Colors.white,
controller: _tabController,
indicatorColor: Colors.transparent,
dividerColor: Colors.transparent,
splashBorderRadius: const BorderRadius.all(Radius.circular(10.0)),
tabAlignment: TabAlignment.center,
tabs: [
const Tab(
icon: Icon(FontAwesomeIcons.plug, size: 21.0),
child: Text(
"Connect",
style: tabTextStyle,
)
),
const Tab(
icon: Icon(FontAwesomeIcons.server, size: 21.0),
child: Text(
"Server",
style: tabTextStyle,
)
),
Container() // tab index 2
]
)
),
body: TabBarView(
controller: _tabController,
children: [
ConnectToServerTab(nicknameController: nicknameController, ipPortController: ipPortController),
CreateServerTab(nicknameController: nicknameController, ipPortController: ipPortController, maxPlayers: maxPlayers, onMaxPlayersChanged: (value) {
setState(() {
maxPlayers = value;
});
}),
// Settings
]
)
),
);
}
}
2
Answers
In this zone when i clicked Tab didn't work.
You suggested 2 solutions
Approach 1: Make settings a tab
TabBar
design limitations made this approach impractical. To achieve this, it would have required something aSpacer
but it’s not possible to use it so the other solution would be calculating manual widths to separate Settings from other tab Server. This would be overly complicated and code would become ugly.Approach 2: Make settings an action item but behave like a tab
This was a tricky solution because when you only have one
TabController
that is shared betweenTabBar
andTabBarView
with a different number of items, trying to navigate to a non-existent index in theTabBar
will display the content but cause theTabBar
to crash.To address this, I used two
TabController
s: one for theTabBar
and another for theTabBarView
.Next, the tabs in TabBar were wrapped in
GestureDetector
. Now, when any tab is clicked, we run:This changes the state of both tab controllers and also updates the color of the selected tab. The reason for changing the color is that when the settings icon button is clicked,
_tabController2
changes to index 2, but_tabController
remains at index 1, meaning it would still appear selected. Since TabBar must have at least one selected tab, we change the selected color to black to make it look unselected. In this case, we want Settings to be highlighted instead.Also to make the tabs not take the whole width to look like in image I needed to set
isScrollable: true
forTabBar
.Anyway it’s tricky solution check the code below, just copy paste it to your main.dart. I had to replace the missing widgets with custom ones and comment out some styles and window management plugin