kdsuneraavinash / theme_provider

Easy to use, customizable and pluggable Theme Provider.
https://pub.dartlang.org/packages/theme_provider
MIT License
152 stars 28 forks source link

Changing the theme rebuilds app with a custom navigator #18

Open ahhmino opened 3 years ago

ahhmino commented 3 years ago

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),
      ),
    );
  }
}