Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing the color and text of AppBar based on the currently viewed page

Tags:

flutter

dart

I have a TabBarView that navigates between the pages in my app. Is there a way to change/override the text and the color of the main AppBar based on the currently viewed page, instead of creating an AppBar for each page separately?

This is how my pages are setup

My routes are defined in the main function as follows:

routes: <String, WidgetBuilder>{
            "/Home": (BuildContext context) => new first.Home(),
            "/Support": (BuildContext context) => new second.Support(),

          }

Tabs class

        class Tabs extends StatefulWidget {

          @override
          TabsState createState() => new TabsState();
        }

    class TabsState extends State<Tabs> with SingleTickerProviderStateMixin {
      TabController controller;

      @override
      void initState() {
        super.initState();

        controller = new TabController(length: 5, vsync: this);

      }

      @override
      void dispose() {
        controller.dispose();
        super.dispose();

      }
      @override
      Widget build(BuildContext context) {

      return new Scaffold(
        appBar: new AppBar(
          centerTitle: true,
          title: new Text('App'), backgroundColor: Colors.blue,
          bottom: new TabBar(
              controller: controller,
              tabs: <Tab>[
                new Tab (icon: new Icon(Icons.home), text: 'Home',),
                            new Tab (icon: new Icon(Icons.mail), text:'Support'),
              ]),
        ),
        body: new TabBarView(
          controller: controller,
          children: <Widget>[
            new first.Home(),
            new second.Support(),

          ],
        ),
      );
    }      
like image 387
Shady Aziza Avatar asked Jul 26 '17 12:07

Shady Aziza


People also ask

How do I change Text color in AppBar?

Step 1: Locate the MaterialApp widget. Step 2: Inside the MaterialApp, add the theme parameter with ThemeData class assigned. Step 3: Inside the ThemeData add the appBarTheme parameter and then assign the AppBarTheme class. Step 4: Inside the AppBarTheme , specify the foregroundColor parameter and set the color.

How can I change the color of AppBar?

Just go to res/values/styles.edit the xml file to change the color of action bar.

How do you change the Text color on Flutter?

Step 1: Locate the file where you have placed the Text widget. Step 2: Inside the Text widget, add the Style parameter and assign the TextStyle widget. Step 3: Inside the TextStyle widget, add the color parameter and set the color of your choice. For example, color: Colors.

How do I change my AppBar color to white in Flutter?

Example 2: Change Color of App Bar in Scaffold In this application, we are setting the app bar color in Scaffold. Run this example Flutter Application in your Android or Apple device. You should get Application Bar with color set to Color(0xff885566) .


2 Answers

If you use a PageView instead of a TabBarView, you can specify an onPageChanged function that allows you to change the state, therefore rebuilding the widget.

Here's some code I'm working on, the title is changed in the appbar but the concept is fundamentally the same:

// Copyright 2017 <Abhi Agarwal>
// Refer to LICENSE

// Dart Imports

// Flutter Imports
import 'package:flutter/material.dart';

// Package Imports
import 'package:shared_preferences/shared_preferences.dart'
    show SharedPreferences;

// Local Imports
import '../calendar/calendar_view.dart' show CalendarView;
import '../error/error_screen.dart' show ErrorScreen;
import '../homework/homework_view.dart' show HomeworkView;
import '../loading/loading_screen.dart' show LoadingScreen;

import 'page.dart' show Page;

class MainView extends StatefulWidget {
  MainView({Key key, this.initialIndex = 0, SharedPreferences prefs})
      : pages = _makePagesList(prefs),
        super(key: key);
  final int initialIndex;
  final List<Page> pages;

  static List<Page> _makePagesList(SharedPreferences prefs) => <Page>[
        CalendarView.page(),
        new Page(
          page: new ErrorScreen(error: "Hello World"),
          title: "Schedule",
          iconData: Icons.schedule,
        ),
        HomeworkView.page(),
        new Page(
          page: new LoadingScreen(),
          title: "Settings",
          iconData: Icons.settings,
        ),
      ];

  @override
  _MainViewState createState() => new _MainViewState();
}

class _MainViewState extends State<MainView> {
  PageController _controller;
  int _index;

  @override
  void initState() {
    super.initState();
    _controller = new PageController(initialPage: widget.initialIndex);
    _index = widget.initialIndex;
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }

  void _handlePageChange(int index) => setState(() => _index = index);

  void _navigateToPage(int index) => _controller.animateToPage(
        index,
        duration: const Duration(milliseconds: 300),
        curve: Curves.ease,
      );

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text(
          widget.pages[_index].title,
          style: new TextStyle(
            fontFamily: Theme.of(context).textTheme.title.fontFamily,
          ),
        ),
        backgroundColor: Theme.of(context).primaryColor,
      ),
      bottomNavigationBar: new BottomNavigationBar(
        type: BottomNavigationBarType.shifting,
        items: widget.pages
            .map((Page page) => new BottomNavigationBarItem(
                  icon: new Icon(
                    page.iconData,
                    color: Theme.of(context).primaryColor,
                  ),
                  title: new Text(
                    page.title,
                    style: new TextStyle(
                      color: Theme.of(context).primaryColor,
                    ),
                  ),
                  backgroundColor: Theme.of(context).canvasColor,
                ))
            .toList(),
        onTap: _navigateToPage,
        currentIndex: _index,
      ),
      floatingActionButton: widget.pages[_index].useFab
          ? new FloatingActionButton(
              tooltip: widget.pages[_index].tooltip,
              child: widget.pages[_index].fab,
              onPressed: () => widget.pages[_index].onPressed(context),
            )
          : null,
      body: new PageView(
        controller: _controller,
        children: widget.pages.map((Page page) => page.page).toList(),
        onPageChanged: _handlePageChange,
      ),
    );
  }
}
like image 192
Abhi Agarwal Avatar answered Sep 19 '22 00:09

Abhi Agarwal


I modified this code to add support for text and color change i guess

https://flutter.io/catalog/samples/tabbed-app-bar/

I apologize for the ugliness for the code. All I did was change all the classes to stateful widget, add an setstate icon selector, change the widget so there is an onPressed callback

  import 'package:flutter/material.dart';

  class MainApp extends StatefulWidget {
    MainApp({Key key, this.title}) : super(key: key);

    // This widget is the home page of your application. It is stateful,
    // meaning that it has a State object (defined below) that contains
    // fields that affect how it looks.

    // This class is the configuration for the state. It holds the
    // values (in this case the title) provided by the parent (in this
    // case the App widget) and used by the build method of the State.
    // Fields in a Widget subclass are always marked "final".

    final String title;
    @override
    TabbedAppBarSample createState() => new TabbedAppBarSample();
  }
  class TabbedAppBarSample extends State<MainApp> {
    Choice _choice;
    initState(){
      super.initState();
      _choice = choices[0];
    }
    void _select(var c){
      setState((){
        _choice = c;
      });

    }

    @override
    Widget build(BuildContext context) {
      return new MaterialApp(
        home: new DefaultTabController(

          length: choices.length,
          child: new Scaffold(
            appBar: new AppBar(
              //dynamically create appbar colors
              backgroundColor: new Color(_choice.color),
              title: new Text(_choice.title),
              bottom: new TabBar(
                isScrollable: true,
                tabs: choices.map((Choice choice) {
                   //change to iconbutton
                  return new IconButton(
                    icon: new Icon(choice.icon),
                    onPressed: (){_select(choice);},
                  );
                }).toList(),
              ),
            ),
            body:
            new TabBarView(
              children: choices.map((Choice choice) {
                return new Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: new ChoiceCard(choice: choice),
                );
              }).toList(),
            ),
          ),
        ),
      );
    }
  }

  class Choice {
    const Choice({ this.title, this.icon, this.color});
    final String title;
    final IconData icon;
    final num color;
  }

  const List<Choice> choices = const <Choice>[
    const Choice(title: 'CAR', icon: Icons.directions_car, color:  0xFFE0F7FA),
    const Choice(title: 'BICYCLE', icon: Icons.directions_bike, color: 0x00ff0000),
    const Choice(title: 'BOAT', icon: Icons.directions_boat, color: 0xFF42A5F5),
    const Choice(title: 'BUS', icon: Icons.directions_bus, color: 0x0),
    const Choice(title: 'TRAIN', icon: Icons.directions_railway, color: 0xFFEFFFFF),
    const Choice(title: 'WALK', icon: Icons.directions_walk, color: 0x0000ff00),
  ];
  class ChoiceCard extends StatefulWidget {
    ChoiceCard({Key key, this.choice}) : super(key: key);
    final Choice choice;
    @override
    _ChoiceCard createState() => new _ChoiceCard();
  }
  class _ChoiceCard extends State<ChoiceCard> {


    @override
    Widget build(BuildContext context) {
      final TextStyle textStyle = Theme.of(context).textTheme.display1;

      return new Card(
        color: Colors.white,
        child: new Center(
          child: new Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              new Icon(widget.choice.icon, size: 128.0, color: textStyle.color),
              new Text(widget.choice.title, style: textStyle),
            ],
          ),
        ),
      );
    }
  }

  void main() {
    runApp(new MainApp());
  }

I am a bit annoyed because my code above is similar to actual answer the op needed. The only difference between my code above and what the op wanted is that I added the on change to the tabcontroller instead of the button itself

Here is the code

 import 'package:flutter/material.dart';
 void main() {
   runApp(new MyApp());
 }
 class MyApp extends StatelessWidget{
   Widget build(BuildContext context) {
     return new MaterialApp(
       title: 'Nothing',
       theme: new ThemeData(
         primarySwatch: Colors.blue,
       ),
       home: new Tabs(),
     );
   }

 }
 class Tabs extends StatefulWidget {
   @override
   TabsState createState() => new TabsState();
 }
 class TabsState extends State<Tabs> with SingleTickerProviderStateMixin {
   TabController controller;
   //create internal state
   Choice _choice;
   @override
   void initState() {
     super.initState();
     //try to make the length to
     controller = new TabController(length: 5, vsync: this);
     //add listener to add change index callback
     //https://docs.flutter.io/flutter/material/TabController-class.html
     controller.addListener(_select);
     _choice = choices[0];

   }
   @override
   void dispose() {
     controller.dispose();
     super.dispose();
   }

   void _select(){
     setState((){
       _choice = choices[controller.index];
     });

   }
   @override
   Widget build(BuildContext context) {
     return new Scaffold(
         appBar: new AppBar(
           centerTitle: true,
           title: new Text(_choice.title), backgroundColor: new Color(_choice.color),
           bottom: new TabBar(
               controller: controller,
               tabs: <Tab>[
                 new Tab( icon: new Icon(choices[0].icon), text: 'Home',),
                 new Tab (icon: new Icon(choices[1].icon), text:'Support'),
               ]),
         ),
         body: new TabBarView(
           controller: controller,
           children: <Widget>[
             //dummy page
             new MyHomePage(),
             new  Center( child: new Text('dummy page 2')),

           ],
         ),
     );
   }
 }
 class Choice {
   const Choice({ this.title, this.icon, this.color});
   final String title;
   final IconData icon;
   final num color;
 }
 //create a list
 const List<Choice> choices = const <Choice>[
   const Choice(title: 'Home', icon: Icons.home, color:  0x0),
   const Choice(title: 'Support', icon: Icons.mail, color: 0xFF42A5F5),

 ];


 class MyHomePage extends StatefulWidget {
   @override
   _MyHomePageState createState() => new _MyHomePageState();
 }
 class _MyHomePageState extends State<MyHomePage> {
   @override
   Widget build(BuildContext context) {
     return new Center(
       child: new Text('dummy page'),
     );
   }
 }
like image 32
user1462442 Avatar answered Sep 20 '22 00:09

user1462442