2

I'm trying to build a simple app structure with an appBar, tabBar and 3 tabView pages. Each of these pages will have a different background color. I would like this background color to cover the full screen (ie, the space taken up by the AppBar, too) . Therefore, I need the color of the AppBar to change as the user switches between tabs.

This is how far I've got:

import 'package:flutter/material.dart';

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  Color PrimaryColor = Colors.teal[400];

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
            elevation: 0,
            backgroundColor: PrimaryColor,
            bottom: TabBar(
              isScrollable: false,
              indicatorColor: Colors.white,
              indicatorWeight: 5,
              onTap: (index) {
                setState(() {
                  switch (index) {
                    case 0:
                      PrimaryColor = Colors.teal[400];
                      break;
                    case 1:
                      PrimaryColor = Colors.orange[500];
                      break;
                    case 2:
                      PrimaryColor = Colors.pink[500];
                      break;
                    default:
                  }
                });
              },
              tabs: [
                Tab(text: ''),
                Tab(text: ''),
                Tab(text: ''),
              ],
            )),
        body: TabBarView(
          children: [
            Container(
              color: Colors.teal[400],
            ),
            Container(
              color: Colors.orange[500],
            ),
            Container(
              color: Colors.pink[500],
            ),
          ],
        ),
      ),
    );
  }
}

This almost achieves the UI that I want, but the background only changes when the tabBar buttons are pressed, not when the swipe gesture is used to change between tabs.

Would be really grateful for some guidance on how to rectify this. Thank you.

This image shows a mockup of the UI of the 3 tab screens

This image shows a mockup of the transition between tabs 1 and 2, where the whole background, including that of the app Bar, changes on swipe

John
  • 23
  • 4

2 Answers2

0

this is because what changes the color is this onTap function

 onTap: (index) {
                setState(() {
                  switch (index) {
                    case 0:
                      PrimaryColor = Colors.teal[400];
                      break;
                    case 1:
                      PrimaryColor = Colors.orange[500];
                      break;
                    case 2:
                      PrimaryColor = Colors.pink[500];
                      break;
                    default:
                  }
                });
              },

which is just called on tap gesture. the problem is solved in the code below

class Home extends StatefulWidget {

@override _HomeState createState() => _HomeState(); }

class _HomeState extends State<Home> with TickerProviderStateMixin {
  Color primaryColor;
  TabController _tabController;
  TabController _tabControllerA;

  @override
  void initState() {
    super.initState();
    _tabController = TabController(
      vsync: this,
      length: 3,
      initialIndex: 0,
    );

    _tabController.addListener(() {
      _handleTabSelection();
    });
  }

  void _handleTabSelection() {
    _tabController.index = _tabController.index;
    setState(() {
      switch (_tabController.index) {
        case 0:
          primaryColor = Colors.teal[400];
          break;
        case 1:
          primaryColor = Colors.orange[500];
          break;
        case 2:
          primaryColor = Colors.pink[500];
          break;
        default:
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          elevation: 0,
          backgroundColor: primaryColor,
          bottom: TabBar(
            isScrollable: false,
            indicatorColor: Colors.white,
            indicatorWeight: 5,
            controller: _tabController,
            onTap: (index) {
              setState(
                () {
                  switch (index) {
                    case 0:
                      primaryColor = Colors.teal[400];
                      break;
                    case 1:
                      primaryColor = Colors.orange[500];
                      break;
                    case 2:
                      primaryColor = Colors.pink[500];
                      break;
                    default:
                  }
                },
              );
            },
            tabs: [
              Tab(text: 'home'),
              Tab(text: 'another one'),
              Tab(text: 'last one'),
            ],
          ),
        ),
        body: TabBarView(
          controller: _tabController,
          children: [
            Container(
              color: primaryColor,
            ),
            Container(
              color: primaryColor,
            ),
            Container(
              color: primaryColor,
            ),
          ],
        ),
      ),
    );
  }
}

this will work

biniyam112
  • 956
  • 1
  • 11
  • 17
  • Thanks for looking at this. This code doesn't seem to produce a different effect to my original code? – John Dec 05 '20 at 07:34
0

If you want transparency in the AppBar when the color change you can use the Stack Widget to place the TabBar above the pages:

DefaultTabController(
  length: 3,
  child: Scaffold(
    body: Stack(
      alignment: Alignment.topCenter,
      children: [
        TabBarView(
          children: [
            Container(
              padding: const EdgeInsets.only(top: 132.0), //note that without this padding the content of the page will apear behind the TabBar
              color: Colors.teal[400],
            ),
            Container(
              color: Colors.orange[500],
            ),
            Container(
              color: Colors.pink[500],
            ),
          ],
        ),

        Column(
          children: [
            SizedBox(height: 50.0),
            Text(
              'Title',   //A text to represent the title of the image
              textAlign: TextAlign.center,
              style: TextStyle(fontSize: 30.0, color: Colors.white),
            ),
            TabBar(
              isScrollable: false,
              indicatorColor: Colors.white,
              indicatorWeight: 5,
              onTap: (index) {},
              tabs: [
                Tab(text: 'Home'),
                Tab(text: 'Groups'),
                Tab(text: 'Profile'),
              ],
            ),
          ],
        )
      ],
    ),
  ),
);
Try
  • 3,109
  • 3
  • 11
  • 15
  • @The padding that you've inserted to stop the page content sitting behind the tabBar, would this be responsive between devices despite being a hardcoded size? – John Dec 05 '20 at 07:42
  • I tested it on cell phones and tablets and the result was the same, hardcode is never the best option but for now I have no other solution. – Try Dec 05 '20 at 15:32