This is a TabBar which animates when the index is selected. Is there a way to make the long text LOOOOT that is animating not over-lapping the TabBar, or just animate behind the TabBar's layout?
TabTest
class TabTest extends StatefulWidget {
@override
_TabTestState createState() => _TabTestState();
}
class _TabTestState extends State<TabTest> with TickerProviderStateMixin {
late TabController _tabController;
late List<AnimationController> _animationControllers;
@override
void initState() {
super.initState();
_tabController = TabController(length: 4, vsync: this)
..addListener(_listener);
_animationControllers = List.generate(
4,
(i) => AnimationController(
vsync: this,
duration: Duration(milliseconds: 750),
reverseDuration: Duration(milliseconds: 350),
));
}
@override
Widget build(BuildContext context) {
Widget _tab(IconData iconData, String text) {
const _tabTextStyle = TextStyle(
fontWeight: FontWeight.w300, fontSize: 12, color: Colors.black);
return SizedBox(
height: 50,
child: Tab(
icon: Icon(iconData, color: Colors.black),
child: Text(text, style: _tabTextStyle),
),
);
}
List<Widget> _tabs = [
_tab(Icons.card_giftcard, 'LOOOOOOOTTTT'),
_tab(Icons.confirmation_num_outlined, 'Voucher'),
_tab(Icons.emoji_events_outlined, 'Testing'),
_tab(Icons.wine_bar_outlined, 'Testing'),
];
List<Widget> _animationGenerator() {
return List.generate(
_tabs.length,
(index) => AnimatedBuilder(
animation: _animationControllers[index],
builder: (ctx, child) {
final child = _tabs[index];
final value = _animationControllers[index].value;
final angle = math.sin(value * math.pi * 2) * math.pi * 0.08;
print(angle);
return Transform.rotate(angle: angle, child: child);
}),
);
}
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(100),
child: AppBar(
iconTheme: Theme.of(context).iconTheme,
title: Text(
'Tab Bar',
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w400,
),
),
centerTitle: true,
bottom: PreferredSize(
preferredSize: Size.fromHeight(20),
child: Container(
child: TabBar(
controller: _tabController,
labelPadding: EdgeInsets.only(top: 5.0, bottom: 2.0),
indicatorColor: Colors.black,
tabs: _animationGenerator(),
),
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.white,
spreadRadius: 5.0,
offset: Offset(0, 3))
],
),
),
),
),
),
body: TabBarView(
controller: _tabController,
children: List.generate(
4,
(index) => FittedBox(
child: Text('Tab $index'),
)),
),
);
}
void _listener() {
if (_tabController.indexIsChanging) {
_animationControllers[_tabController.previousIndex].reverse();
} else {
_animationControllers[_tabController.index].forward();
}
}
@override
void dispose() {
super.dispose();
_tabController.removeListener(_listener);
}
}
This is what I have. No package used. Planning to animate the Container
with bottom border of the selected Tab
. (currently using SizedBox
to wrap the Tab
) and animate it behind the TabBar
rather than over-lapping the TabBar
.
EDIT: Include code
CodePudding user response:
Wrap the tab widget with a clipRect.