I want to create a tab bar like the one above which can be swipable with animations. I tried doing this with the default Tab bar widget in Flutter but failed miserably. How can I make this tab bar swipable with animations?
What is the logic behind bringing the selected tab animation down from "Friends" tab to "Family" tab?
I figured out the onHorizontalDrag
property from the GestureDetector
widget to do the swiping but still can't wrap my head around switching the tabs with animation.
It'd be so great if someone could help me with this.
This is made using PageView
and customAppBar. However, if you want clickEvent on tabBaritem, wrap with GestureDetector
make a callBack
or stateManagement
to hold index.
Result
MainWidget
class BU extends StatefulWidget {
BU({Key? key}) : super(key: key);
@override
_BUState createState() => _BUState();
}
class _BUState extends State<BU> {
int _selectedIndex = 0;
final PageController controller = PageController(initialPage: 0);
@override
void initState() {
super.initState();
widgets = [
...List.generate(
5,
(index) => Container(
alignment: Alignment.center,
color: index.isEven ? Colors.cyanAccent : Colors.deepPurple,
child: Text(
"Item $index",
style: TextStyle(fontSize: 44),
),
),
)
];
controller.addListener(() {
if (controller.hasClients) {
setState(() {
/// you can ceil foor
_selectedIndex = controller.page!.toInt();
});
}
});
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
late List<Widget> widgets;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
AppBar(
selectedItem: _selectedIndex,
),
Expanded(
child: Container(
width: double.infinity,
child: PageView(
controller: controller,
children: [...widgets],
)),
)
],
),
);
}
}
TabBar
class AppBar extends StatelessWidget {
final int selectedItem;
const AppBar({
Key? key,
required this.selectedItem,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(8),
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
TabItemChip(
isSelected: selectedItem == 0,
text: "Profile",
),
TabItemChip(
isSelected: selectedItem == 1,
text: "About",
),
TabItemChip(
isSelected: selectedItem == 2,
text: "Friends",
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
TabItemChip(
isSelected: selectedItem == 3,
text: "Family",
),
TabItemChip(
isSelected: selectedItem == 4,
text: "Settings",
),
],
)
],
),
);
}
}
TabBarItemChip
class TabItemChip extends StatelessWidget {
final bool isSelected;
final String text;
const TabItemChip({
Key? key,
required this.text,
required this.isSelected,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return AnimatedContainer(
duration: Duration(milliseconds: 400),
height: 40,
width: 140,
alignment: Alignment.center,
decoration: BoxDecoration(
color: isSelected ? Colors.cyanAccent.shade700 : Colors.white,
borderRadius: BorderRadius.circular(12),
),
child: Text(
text,
style: TextStyle(
color: isSelected ? Colors.white : Colors.black,
fontWeight: FontWeight.bold,
),
),
);
}
}