18

I'm trying to change the AppBar title depending on which page the user is on - the pages are controlled by a BottomNavigationBar which loads the different classes(pages)

The only way i've managed to change this is by including a appbar for each page, which i believe is not the way to go ahead.

class HomePage extends StatefulWidget {
  final String title;

  HomePage({Key key, this.auth, this.userId, this.onSignedOut, this.title})
      : super(key: key);

  final BaseAuth auth;
  final VoidCallback onSignedOut;
  final String userId;

  @override
  State<StatefulWidget> createState() => new _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _currentIndex = 0;
  final List<Widget> _children = [
    Projects(),
    TimedProject(),
    Overview(),
    Clients(),
  ];

  GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey();

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: Text('TITLE I NEED TO CHANGE DEPENDING ON PAGE',
          style: TextStyle(color: Colors.black),
        ),

        backgroundColor: Colors.white,
      ),
      endDrawer: AppDrawer(),
      body: _children[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        onTap: onTabTapped,
        currentIndex: _currentIndex,
        selectedItemColor: Theme.of(context).primaryColor,
        type: BottomNavigationBarType.fixed,
        items: [
          new BottomNavigationBarItem(
            icon: Icon(Icons.storage),
            title: Text('Jobs'),
          ),
          new BottomNavigationBarItem(
            icon: Icon(Icons.timer),
            title: Text('Timer'),
          ),
          new BottomNavigationBarItem(
            icon: Icon(Icons.pie_chart_outlined),
            title: Text('Overview'),
          ),
          new BottomNavigationBarItem(
              icon: Icon(Icons.supervisor_account), title: Text('Clients'))
        ],
      ),
    );
  }

  void onTabTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }
}
Kylie Walker
  • 215
  • 1
  • 3
  • 10

6 Answers6

25

Create a variable that holds the appbar title or you can use the same title variable that is passed in your HomePage class but you have to remove the final.

If you are using the title variable in HomePage class, make sure to use "widget.title"

class HomePage extends StatefulWidget {
  final String title;

  HomePage({Key key, this.auth, this.userId, this.onSignedOut, this.title})
      : super(key: key);

  final BaseAuth auth;
  final VoidCallback onSignedOut;
  final String userId;

  @override
  State<StatefulWidget> createState() => new _HomePageState();
 }

class _HomePageState extends State<HomePage> {
  int _currentIndex = 0;
  String _title;

  final List<Widget> _children = [
     Projects(),
     TimedProject(),
     Overview(),
     Clients(),
  ];

  GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey();

 @override
  initState(){
    _title = 'Some default value';
  }


  @override
  Widget build(BuildContext context) {
     return new Scaffold(
       key: _scaffoldKey,
       appBar: AppBar(
       title: Text(_title,
          style: TextStyle(color: Colors.black),
       ),

       backgroundColor: Colors.white,
      ),
  endDrawer: AppDrawer(),
  body: _children[_currentIndex],
  bottomNavigationBar: BottomNavigationBar(
    onTap: onTabTapped,
    currentIndex: _currentIndex,
    selectedItemColor: Theme.of(context).primaryColor,
    type: BottomNavigationBarType.fixed,
    items: [
      new BottomNavigationBarItem(
        icon: Icon(Icons.storage),
        title: Text('Jobs'),
      ),
      new BottomNavigationBarItem(
        icon: Icon(Icons.timer),
        title: Text('Timer'),
      ),
      new BottomNavigationBarItem(
        icon: Icon(Icons.pie_chart_outlined),
        title: Text('Overview'),
      ),
      new BottomNavigationBarItem(
          icon: Icon(Icons.supervisor_account), title: Text('Clients'))
    ],
  ),
);
}

   void onTabTapped(int index) {
     setState(() {
     _currentIndex = index;
      switch(index) { 
       case 0: { _title = 'Jobs'; } 
       break; 
       case 1: { _title = 'Timer'; } 
       break;
       case 2: { _title = 'Overview'; } 
       break;
       case 3: { _title = 'Clients'; } 
       break; 
      } 
     });
   }
}
fadhli-sulaimi
  • 686
  • 12
  • 17
3

Thanks for the solution, is there away to take the bottom nav and out it in its own .dart file like

bottomNavigationBar: BottomNavBar(),

and get the selected tab index

class _HomeScreen2State extends State<HomeScreen2> {
  //Hold current Tab Index
  int _selectTab = 0;
  final _pageOptions = [
    HomeScreen(),
    NewOrderScreen(),
    OrderHistoryScreen(),
    ContactScreen(),
  ];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Gift Shop Dashboard'),
      ),
      body: _pageOptions[_selectTab],
      bottomNavigationBar: BottomNavBar(),
    );
  }
}
Rahul Kadukar
  • 858
  • 3
  • 15
  • 35
Ian Perera
  • 241
  • 3
  • 9
  • You should take a look of State management in Flutter , and start with a basic example ( using `changenotifier`, `provider`) . This mechanism will allow you to update with a good design pattern your app title. https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple – bwnyasse Aug 24 '19 at 06:13
0

To separate BottomNavigationBar in a different .dart file, for example, in config.dart:

import 'package:flutter/material.dart';

class Config {

  static List<BottomNavigationBarItem> navigationBarItems = [
    BottomNavigationBarItem(
      icon: Icon(
        Icons.date_range,
      ),
      title: Text(
        "Calendar",
      ),
    ),
    BottomNavigationBarItem(
      icon: Icon(
        Icons.list, // event_note
      ),
      title: Text(
        "List",
      ),
    ),
    BottomNavigationBarItem(
      icon: Icon(
        Icons.bookmark_border, // grid_on 
      ),
      title: Text(
        "Bookmarks",
      ),
    ),
    BottomNavigationBarItem(
      icon: Icon(
        Icons.account_circle,
      ),
      title: Text(
        "Me",
      ),
    ),
  ];

  static BottomNavigationBar navigationBar = BottomNavigationBar(
    items: navigationBarItems,
    type: BottomNavigationBarType.fixed,
    fixedColor: Colors.red,
  );

}

and in main.dart:

import 'package:flutter/material.dart';
import 'config.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Hello',
      theme: ThemeData(
        primarySwatch: Colors.blueGrey,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  HomePage({Key key}) : super(key: key);

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

class _HomePageState extends State<HomePage> {

  int _index = 0;
  Text _title;

  _onTap(int index) {
    setState(() {
      _index = index;
      _title = Config.navigationBarItems[_index].title;
    });
  }

  @override
  void initState() {
    _title = Config.navigationBarItems[_index].title;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: _title,
      ),
      body: Container(
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _index,
        type: Config.navigationBar.type,
        fixedColor: Config.navigationBar.fixedColor,
        items: Config.navigationBar.items,
        onTap: _onTap,
      ),
    );
  }
}
ohho
  • 50,879
  • 75
  • 256
  • 383
0

just make condition in ontap

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 1;
String appbarTitleString = "Home";
var appBarTitleText = new Text("Home");
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
static const List<Widget> _widgetOptions = <Widget>[
Text(
  'Index 0: Profile',
  style: optionStyle,
),
Text(
  'Index 1: Home',
  style: optionStyle,
),
Text(
  'Index 2: More',
  style: optionStyle,
),
 ];

@override
Widget build(BuildContext context) {
return Scaffold(

  appBar: AppBar(
    title: appBarTitleText,
  ),
  body: Center(
    child: _widgetOptions.elementAt(_selectedIndex),
  ),
  bottomNavigationBar: BottomNavigationBar(
    items: const <BottomNavigationBarItem>[
      BottomNavigationBarItem(
        icon: Icon(Icons.business),
        title: Text('Profile'),
      ),
      BottomNavigationBarItem(
        icon: Icon(Icons.home),
        title: Text('Home'),
      ),
      BottomNavigationBarItem(
        icon: Icon(Icons.school),
        title: Text('More'),
      ),
    ],
    currentIndex: _selectedIndex,
    selectedItemColor: Colors.amber[800],
    onTap: _onItemTapped,
  ),
);
}
void _onItemTapped(int index) {
setState(() {
  _selectedIndex = index;
  if (index == 0){
    appbarTitleString = "Profile" ;
    appBarTitleText = new Text(appbarTitleString);
  }else if (index == 1){
    appbarTitleString = "Home" ;
    appBarTitleText = new Text(appbarTitleString);
  }else if(index == 2){
    appbarTitleString = "More" ;
    appBarTitleText = new Text(appbarTitleString);
  }
});
}
}
Chris Catignani
  • 5,040
  • 16
  • 42
  • 49
0

it is too Simple, using only two variable we can handle it.

Take Two Variables like:

   int _selectedIndex = 0;
   String _page_title = "DashBoard";

and Replace page title on every index changed. like as below,

 void _onItemTapped(int index) {
     setState(() {
     _selectedIndex = index;

  if (index == 0) {
    _page_title = "DashBoard";
  } else if (index == 1) {
    _page_title = "Search";
  } else if (index == 2) {
    _page_title = "Setting";
  } else if (index == 3) {
    _page_title = "Profile";
  }
});

make a list which decide to perform task from selected tab.

 static const List<Widget> _widgetOptions = <Widget>[
    Text(
      'Home 1',
      style: optionStyle,
    ),
    Text(
      'Home 2',
      style: optionStyle,
    ),
    Text(
      'Home 3',
      style: optionStyle,
    ),
    Profile(),
  ];

And adjust code in Build() function as below.

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text(_page_title),
        automaticallyImplyLeading: false, // hide back arrow from appbar
      ),
      body: Center(
        child: _widgetOptions.elementAt(_selectedIndex),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: const <BottomNavigationBarItem>[
          BottomNavigationBarItem(
            icon: Icon(
              Icons.home,
              color: Colors.grey,
            ),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(
              Icons.search,
              color: Colors.grey,
            ),
            label: 'Search',
          ),
          BottomNavigationBarItem(
            icon: Icon(
              Icons.settings,
              color: Colors.grey,
            ),
            label: 'Setting',
          ),
          BottomNavigationBarItem(
            icon: Icon(
              Icons.face_retouching_natural_sharp,
              color: Colors.grey,
            ),
            label: 'Profile',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.blue,
        onTap: _onItemTapped,
      ),
    );
  }
}

☻♥ Done.

0

In case you also have different actions, leadings, etc for different pages, You can have different appbars in separate files and import them like pages.

static final List<Widget> _pages = [
  const HomeScreen(),
  const BookingScreen(),
  const AccountScreen(),
];

static final List<Widget> _appBars = [
  const HomeAppBar(),
  const BookingAppBar(),
  const AccountAppBar(),
];

Then you can have variable:

int _selectedIndex = 0;

Your onTapped function will be like:

void _onItemTapped(int index) {
  setState(() {
    _selectedIndex = index;
  });
}

Your build would be like this:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: PreferredSize(
      preferredSize: const Size.fromHeight(56), // 56 is default height
      child: _appBars[_selectedIndex],
    ), // PreferredSize

    body: _pages[_selectedIndex],

    bottomNavigationBar: BottomNavigationBar(
      currentIndex: _selectedIndex,
      onTap: _onItemTapped,
      items: const [
        BottomNavigationBarItem(
          icon: Icon(Icons.home_rounded),
          label: "Home",
        ), // BottomNavigationBarItem
        BottomNavigationBarItem(
          icon: Icon(Icons.schedule_rounded),
          label: "Bookings",
        ), // BottomNavigationBarItem
        BottomNavigationBarItem(
          icon: Icon(Icons.person_rounded),
          label: "Account",
        ), // BottomNavigationBarItem
      ],
    ), // BottomNavigationBar
  ); // Scaffold
}
Anushka Chauhan
  • 349
  • 3
  • 10