dart 在Flutter中按下按钮时更改应用程序的主题

uqjltbpv  于 2023-06-19  发布在  Flutter
关注(0)|答案(1)|浏览(131)

我试图改变应用程序的主题,通过按下开关按钮,每个按钮更改为一个主题。
但是我需要帮助来处理按钮的 onPressed {},这是整个应用程序的一部分屏幕:

List<AppTheme> themesNotInClass = [
        AppTheme(
          id: 'superhero_theme',
          description: "Super Hero Theme",
          data: superheroTheme,
        )
      ];

class ThemeChooser extends StatelessWidget {
  bool button1pressed = false;
  bool button2pressed = false;
  bool button3pressed = false;

  // Defining the route name of the screen to be accessed in other screens
  ThemeChooser({
    Key? key
  }) : super(key: key);
  static const String routeName = "/testingthemechooser";

  @override
  Widget build(BuildContext context) {
     return ThemeProvider(
      // Defining the booleans
      saveThemesOnChange: true,
      loadThemeOnInit: false,
      onInitCallback: (controller, previouslySavedThemeFuture) async {
        String? savedTheme = await previouslySavedThemeFuture;
        if (button1pressed == true) 
        if (savedTheme != null) {
          controller.setTheme(savedTheme);
        }
        else {
          Brightness platformBrightness = SchedulerBinding.instance.window.platformBrightness;
          if (platformBrightness == Brightness.dark) {
            controller.setTheme('superhero_theme');
          }}
          controller.forgetSavedTheme();
        }
      },
      themes: themesNotInClass,
      child: const MainWidget(button1pressed: false),
    );
  }
}

class MainWidget extends StatefulWidget {
  final bool button1pressed;
  const MainWidget({Key? key, required this.button1pressed}) : super(key: key);
  @override
  _MainWidgetState createState() => _MainWidgetState();
}
class _MainWidgetState extends State<MainWidget> {
  late bool button1pressed;
  late bool button2pressed;
  late bool button3pressed;
  @override
  void initState() {
    super.initState();
    button1pressed = widget.button1pressed;
  }
  @override
  Widget build(BuildContext context) {
    final themeController = CustomThemeController(
      providerId: 'provider_provider', 
      themes: {
        'superhero_theme': superheroTheme, 
        'blue_theme': ThemeData.light(),
      }, 
      defaultThemeId: 'default_theme'
    );
    return MaterialApp(
      title: 'Theme Chooser',
      home: ChangeNotifierProvider.value(
        value: themeController,
        child: Scaffold(
          appBar: AppBar(
            title: const Text('Theme Chooser'),
          ),
          body: Consumer<CustomThemeController>(
            builder: (context, controller, _) {
              return ListView(
                children: [
                  ListTile(
                    title: const Text('Super Hero'),
                    trailing: ElevatedButton(
                      onPressed: button1pressed
                          ? null
                          : () {
                              setState(() {
                                button1pressed = true;
                              });
                            },
                      child: const Text('Switch'),
                    ),
                  ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

class ThemeOptions implements AppThemeOptions {
  final Color specificButtonColor;
  ThemeOptions(this.specificButtonColor);
}

class CustomThemeController extends ChangeNotifier {
  final String providerId;
  final Map<String, ThemeData> themes;
  final String defaultThemeId;
  final bool saveThemesOnChange;
  final bool loadThemeOnInit;
  final ThemeData _currentTheme;

  CustomThemeController({
    required this.providerId,
    required this.themes,
    required this.defaultThemeId,
    this.saveThemesOnChange = true,
    this.loadThemeOnInit = false,
  }) : _currentTheme = themes[defaultThemeId] ?? ThemeData.light();

  ThemeData get currentTheme => _currentTheme;

}

我尝试了很多方法来实现这个功能,但没有得到积极的结果,我想更改按钮1按下,然后将结果发送到主类,即 * themchooser *

vngu2lb8

vngu2lb81#

您应该将MaterialApp Package 在StatefulWidget中。

import 'package:flutter/material.dart';

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

final Map<String, ThemeData> themes = {
  'defaultTheme': ThemeData(
    colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
    useMaterial3: true,
  ),
  'firstCustomTheme': ThemeData(
    colorScheme: ColorScheme.fromSeed(seedColor: Colors.red),
    useMaterial3: true,
  ),
  'secondCustomTheme': ThemeData(
    colorScheme: ColorScheme.fromSeed(seedColor: Colors.grey),
    useMaterial3: true,
  ),
};

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ThemeData _theme = themes['defaultTheme']!;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: _theme,
      home:
          MyHomePage(onThemeChange: (ThemeData newTheme) => setState(() => _theme = newTheme)),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.onThemeChange});

  final Function onThemeChange;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() => setState(() => _counter++);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('Example Theme Change'),
        actions: [
          DropdownButton<String>(
            icon: const Icon(Icons.arrow_downward),
            elevation: 16,
            onChanged: (String? value) {
              final newTheme = themes[value];
              if (newTheme == null) throw Exception('NullThemeException for Value: $value');
              widget.onThemeChange(newTheme);
            },
            items: themes.keys.map<DropdownMenuItem<String>>((String value) {
              return DropdownMenuItem<String>(
                value: value,
                child: Text(value),
              );
            }).toList(),
          ),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

我写这个例子是为了传递onThemeChange函数,但对于大型项目,最好创建一个自定义服务,这样DropdownButtononChange函数就像这样:

onChanged: (color) {
            if (color != null) {
              final myApp = context.findAncestorStateOfType<_MyAppState>();
              myApp?._changeThemeColor(color);
            }
          },

希望能帮上忙!

相关问题