Skip to content

Changing the theme rebuilds app with a custom navigator #18

@ahhmino

Description

@ahhmino

I'm using a custom navigator in my flutter app, and it seems to not play well with this plugin - whenever a theme is switched (using either nextTheme() or setThemeId(themeId), the app reverts to the initial route of the navigator and the initial state of that route. No state or route information is saved. Is there any workaround for this? Using flutter 2.2.1

I have two reproducible examples, one with a custom navigator and one without:

With custom navigator:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ThemeProvider(
      child: ThemeConsumer(
        child: Builder(
          builder: (context) => MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeProvider.themeOf(context).data,
            home: MainNavigator(),
          ),
        ),
      ),
    );
  }
}

class MyCounterPage extends StatefulWidget {
  MyCounterPage({Key? key, required this.title}) : super(key: key);
  final String title;

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

class _MyCounterPageState extends State<MyCounterPage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the FAB this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            TextButton(
                onPressed: () => Navigator.of(context).pushNamed("second"),
                child: Text("Tap here to go to the theme page"))
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class MainNavigator extends StatelessWidget {

  MainNavigator({Key? key}) : super(key: key);

  final GlobalKey<NavigatorState> navigatorKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
        onWillPop: () async {
          return false;
        },
        child: Navigator(
          key: navigatorKey,
          initialRoute: "first",
          onGenerateRoute: (settings) {
            if(settings.name == "first") {
              return MaterialPageRoute(builder: (context) =>
                  MyCounterPage(title: 'Flutter Demo Home Page'),
                  settings: settings);
            }
            return MaterialPageRoute(builder: (context) =>
                MyThemePage(title: 'Flutter Demo Home Page'),
                settings: settings);
          },
        )
    );
  }
}

class MyThemePage extends StatefulWidget {
  MyThemePage({Key? key, required this.title}) : super(key: key);
  final String title;

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

class _MyThemePageState extends State<MyThemePage> {
  int _counter = 0;

  void _incrementCounter() {
    ThemeProvider.controllerOf(context).nextTheme();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Press the FAB to change the theme',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

Without custom navigator (using default routes in root material app):

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ThemeProvider(
      child: ThemeConsumer(
        child: Builder(
          builder: (context) => MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeProvider.themeOf(context).data,
            initialRoute: "first",
            onGenerateRoute: (settings) {
              if(settings.name == "first") {
                return MaterialPageRoute(builder: (context) =>
                    MyCounterPage(title: 'Flutter Demo Home Page'),
                    settings: settings);
              }
              return MaterialPageRoute(builder: (context) =>
                  MyThemePage(title: 'Flutter Demo Home Page'),
                  settings: settings);
            },
          ),
        ),
      ),
    );
  }
}

class MyCounterPage extends StatefulWidget {
  MyCounterPage({Key? key, required this.title}) : super(key: key);
  final String title;

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

class _MyCounterPageState extends State<MyCounterPage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the FAB this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
            TextButton(
                onPressed: () => Navigator.of(context).pushNamed("second"),
                child: Text("Tap here to go to the theme page"))
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class MyThemePage extends StatefulWidget {
  MyThemePage({Key? key, required this.title}) : super(key: key);
  final String title;

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

class _MyThemePageState extends State<MyThemePage> {
  int _counter = 0;

  void _incrementCounter() {
    ThemeProvider.controllerOf(context).nextTheme();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Press the FAB to change the theme',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions