Как добавить переключатель для смены темы приложения Flutter?

Я новичок в флаттере и сталкиваюсь с проблемами, пытаясь включить кнопку на панели приложений, которая меняет тему всего приложения.

Это код файла main.dart.

import 'package:flutter/material.dart';
import 'package:qrpay_app/routes/Routes.dart';
import 'module/splash/splash_view.dart';
import 'module/buy/buy_list_view.dart';
import 'module/sell/sell_list_view.dart';
import 'module/shop/shop_list_view.dart';
import 'module/account/account_list_view.dart';
import 'module/contact/contact_list_view.dart';
import 'module/help/help_list_view.dart';
import 'module/receipts/receipts_list_view.dart';
import 'module/about us/about_us_view.dart';
import 'package:qrpay_app/Themes/appThemes.dart';

import 'module/qr/qr_view.dart';

void main() {
  runApp(new MaterialApp(
    title: 'QRPAY Touch-Free',
    theme: new ThemeData(primarySwatch: Colors.red),
    home: SplashPage(),
    routes: {
      Routes.splash: (context) => SplashPage(),
      Routes.buy: (context) => BuyPage(),
      Routes.sell: (context) => SellPage(),
      Routes.shop: (context) => ShopPage(),
      Routes.qr: (context) => QRPage(),
      Routes.account: (context) => AccountPage(),
      Routes.contact: (context) => ContactPage(),
      Routes.help: (context) => HelpPage(),
      Routes.receipts: (context) => ReceiptsPage(),
      Routes.about_us: (context) => AboutUsPage(),
    },
  ));
}

Это код appThemes.dart:

import 'package:flutter/material.dart';

class AppThemes {
  // Simple constructor
  AppThemes._();

  static final ThemeData highContrast = ThemeData(
    primarySwatch: Colors.black,
    primaryTextTheme: TextTheme(
      headline6: TextStyle(color: Colors.white),
    ),
    scaffoldBackgroundColor: Colors.white,
    appBarTheme: AppBarTheme(
      color: Colors.black,
      iconTheme: IconThemeData(
        color: Colors.white,
      ),
      elevation: 30.0,
    ),
  );

  static final ThemeData normalContrast = ThemeData(
    scaffoldBackgroundColor: Colors.white,
    appBarTheme: AppBarTheme(
      color: Colors.red,
      iconTheme: IconThemeData(
        color: Colors.white,
      ),
    ),
  );
}

Я перенаправил дом на splash_view.dart. Это код appThemes.dart:

import 'package:flutter/material.dart';
import 'package:qrpay_app/widget/drawer.dart';
import 'package:qrpay_app/Themes/appThemes.dart';

class SplashPage extends StatefulWidget {
  static const String routeName = '/splash';
  @override
  _SplashPageState createState() => _SplashPageState();
}

class _SplashPageState extends State<SplashPage> {
  void changeContrast() {
    print("High contrast button clicked\nChanging app contrast\n");
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("QRPAY Touch-Free"),
        elevation: 30.0,
        actions: <Widget>[
          ElevatedButton(
              onPressed: () {
                changeContrast();
              },
              child: Text('High Contrast')),
        ],
      ),
      drawer: AppDrawer(),
      body: new Center(
        child: new Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Container(
              child: new Image.asset(
                'res/images/qplogo.png',
                width: MediaQuery.of(context).size.width * .9,
                fit: BoxFit.cover,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Я добавил кнопку с повышенным уровнем, которая должна изменить тему всего приложения. Пожалуйста, помогите с отображением функциональности на основе моих файлов дротика.

Кроме того, я не понимаю, как добавить изменение состояния

Я пытался работать с «провайдером», но я запутался.

Пожалуйста, помогите мне. Кроме того, пожалуйста, дайте мне знать, если вам нужно что-то еще, чтобы лучше понять мою проблему.

Я ценю, что вы все нашли время и помогли мне.

Благодарю вас.


person Aarav Chandra    schedule 26.11.2020    source источник
comment
попробуй поставить коды вместо картинок   -  person Yahya parvar    schedule 26.11.2020


Ответы (2)


Вы можете прочитать статью о Flutter Stream здесь: https://medium.com/@ayushpguptaapg/using-streams-in-flutter-62fed41662e4

Добавьте логическое значение для отслеживания текущей темы

bool isHighContrast = false;

Затем, когда ваш переключатель включен, просто позвоните:

// switch is on, toggle isHighContrast. isHighContrast now equals to true
controller.add(isHighContrast);

А затем слушайте изменения, чтобы обновить весь пользовательский интерфейс:

controller.stream.listen({
  setState({
    theme = AppTheme.highContrast;
  });
})
person Teddichiiwa    schedule 26.11.2020
comment
как реализовать? мне вносить изменения в каждый файл дротика или файл, маршрутизируемый дома? Кроме того, как это изменение отразится на всех страницах приложения? - person Aarav Chandra; 27.11.2020
comment
Вам просто нужно реализовать его в свойстве темы вашего MaterialApp, обязательно поместите свою тему в переменную, поэтому, когда контраст был изменен, вы просто вызываете setState, и каждый экран внутри вашего MaterialApp изменится. - person Teddichiiwa; 27.11.2020
comment
Я изменил вопрос, пожалуйста, просмотрите его, также мне нужна кнопка для изменения темы в зависимости от текущего состояния. Если он в обычном режиме, переключитесь в режим высокой контрастности, а если в режиме высокой контрастности, то переключитесь в нормальный режим. - person Aarav Chandra; 27.11.2020

Самый простой подход — использовать Provider.

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(
    MultiProvider(
      providers: [
      // Used MultiProvider incase you have other providers
        ChangeNotifierProvider<ThemeDataProvider>(
          create: (_) => ThemeDataProvider(),
        ),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    ThemeDataProvider themeDataProvider = Provider.of(context);

    // Pull the theme data from the provider and make a few modification
    // The modifications are for illustration only.  Not required.
    final ThemeData currentTheme = themeDataProvider.themeData.copyWith(
      scaffoldBackgroundColor: themeDataProvider.isDarkTheme ? Colors.yellow[700] : Colors.yellow[300],
      appBarTheme: themeDataProvider.themeData.appBarTheme,
      cardTheme: themeDataProvider.themeData.cardTheme,
    );
    return MaterialApp(
      color: Colors.yellow[100],
      title: 'MyApp',
      theme: currentTheme, //set your theme
      initialRoute: setupRoute,
      onGenerateRoute: Router.generateRoute,
    );
  }
}


class ThemeDataProvider with ChangeNotifier {
  Future<SharedPreferences> _prefs = SharedPreferences.getInstance();

  SharedPreferences prefs;
  bool isInitialized;
  bool _useDarkTheme;
  double _appMargin;
  int _animationDuration = 200;
  ThemeData _themeData;

  ThemeDataProvider() {
    isInitialized = false;
    _initialize();
  }

  void _initialize() async {
    prefs = await _prefs;
    await _loadPrefs();
    _themeData = _buildThemeData();
    _appMargin = 0.0;
    isInitialized = true;
  }

  ThemeData get themeData => _themeData;

  bool get isDarkTheme => _useDarkTheme ?? true;
  double get appMargin => _appMargin;
  int get animDuration => _animationDuration;

  ///
  /// Set the application working margin.
  ///
  void setAppMargin(double appMargin) {
    _appMargin = appMargin;
  }

  void toggleTheme() {
    _useDarkTheme = !_useDarkTheme;
    _savePrefs();
    _themeData = _buildThemeData();
    notifyListeners();
  }

  Future _loadPrefs() async {
    prefs = await _prefs;
    _useDarkTheme = prefs.getBool("useDarkMode") ?? true;
    _themeData = _buildThemeData();
    notifyListeners();
  }

  void _savePrefs() async {
    prefs = await _prefs;
    prefs.setBool("useDarkMode", _useDarkTheme);
  }

// Build your theme data here
      ThemeData _buildThemeData() {
        return ThemeData(
          primarySwatch: isDarkTheme
              ? MaterialColor(4280361249, {
                  50: Color(0xfff2f2f2),
    ...

Добавьте переключатель в любое место и при щелчке вызовите метод toggleTheme.

Это не функциональный код. Это отредактированная версия моего производственного кода.

person JonnyH    schedule 26.11.2020
comment
Я думаю, что это слишком долго для простой задачи или, может быть, я не знаю. Я новичок в флаттере, хотя для меня я действительно хочу, чтобы флаттер имел одну строку кода, которая могла бы изменить тему. - person Aquiko; 14.05.2021