Widget won't overlap other widget

Question

Asked by Phil D on November 08, 2021 (source).

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?

enter image description here

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

Answer

Question answered by Kaushik C (source).

Wrap the tab widget with a clipRect.

ANIMATION DART FLUTTER
SHARE: