简体   繁体   English

Flutter:使用 GetX 实用程序函数时存储语言和主题首选项

[英]Flutter: Storing language and theme preference when using GetX utility functions

Is there any way to store user preferences (and retrieve them on reboot) when using GetX 's utility functions:使用GetX的实用程序功能时,是否有任何方法可以存储用户首选项(并在重新启动时检索它们):

Get.changeTheme(ThemeData().dark)

as well as

Get.updateLocale(Locale('en', 'US'));

So far I am only able to change both, the theme and the language, but I have not found a way in GetX to persevere any of my changes to any sort of storage in order to be loaded when reopening the app the next time.到目前为止,我只能更改主题和语言,但我还没有在 GetX 中找到一种方法来坚持我对任何类型的存储所做的任何更改,以便在下次重新打开应用程序时加载。 Is there anything I am overlooking?有什么我忽略的吗? Is there any way to hook into the startup process and check for some stored values (eg in SharedPreferences ) and pass them to my locale and theme properties in GetMaterialApp ?有什么方法可以连接到启动过程并检查一些存储的值(例如在SharedPreferences中)并将它们传递给我在GetMaterialApp中的localetheme属性?

This is my code:这是我的代码:

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

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      translations: Messages(),
      locale: Get.locale,
      theme: Get.theme,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextButton(
                onPressed: () => {
                      Get.changeTheme(
                          Get.isDarkMode ? ThemeData.light() : ThemeData.dark())
                    },
                child: Text('change_theme'.tr)),
            TextButton(
                onPressed: () => {
                      Get.updateLocale(Get.locale == Locale('en', 'US')
                          ? Locale('de', 'DE')
                          : Locale('en', 'US'))
                    },
                child: Text('change_language'.tr)),
          ],
        ));
  }
}

class Messages extends Translations {
  @override
  Map<String, Map<String, String>> get keys => {
        'en_US': {
          'change_theme': 'Change Theme',
          'change_language': 'Change Language',
        },
        'de_DE': {
          'change_theme': 'Farbschema wechseln',
          'change_language': 'Sprache wechseln',
        }
      };
}

This is easier to do with GetStorage .使用GetStorage更容易做到这一点。

If you're just changing from light to dark theme, it's a matter of storing a simple bool every time the theme is changed.如果您只是从浅色主题更改为深色主题,则每次更改主题时都存储一个简单的布尔值。

Here's one way to do this with a basic settings class.这是使用基本设置 class 执行此操作的一种方法。

class SettingsController extends GetxController {
  ThemeData themeData;

  final box = GetStorage();

  @override // called when you use Get.put before running app
  void onInit() {
    super.onInit();
    _restoreTheme();
  }

  void _restoreTheme() {
    bool isDark = box.read('isDark') ?? true; // null check for first time running this
    if (isDark) {
      themeData = ThemeData.dark();
    } else {
      themeData = ThemeData.light();
    }
  }

  void storeThemeSetting(bool isDark) {
    box.write('isDark', isDark);
  }
}

The themeData variable from the SettingsController class gets initialized depending on the bool value from storage. SettingsController class 中的themeData变量根据存储中的 bool 值进行初始化。 And that themeData file is what you pass into your GetMaterialApp , which looks like this.那个themeData文件就是你传递给你的GetMaterialApp的文件,它看起来像这样。

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final controller = Get.find<SettingsController>();
    return GetMaterialApp(
      theme: controller.themeData,
      title: 'Material App',
      home: StorageDemo(),
    );
  }
}

Then put both of these lines in your Main method before running your app.然后在运行您的应用程序之前将这两行都放入您的 Main 方法中。

  await GetStorage.init();

  Get.put(SettingsController());

Here's a demo page where you can test this.这是一个演示页面,您可以在其中进行测试。

class StorageDemo extends StatelessWidget {
  Widget build(BuildContext context) {
    final controller = Get.find<SettingsController>();
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            TextButton(
              onPressed: () {
                Get.changeTheme(ThemeData.dark());
                controller.storeThemeSetting(true);
              },
              child: Text('Dark Theme'),
            ),
            TextButton(
              onPressed: () {
                Get.changeTheme(ThemeData.light());
                controller.storeThemeSetting(false);
              },
              child: Text('Light Theme'),
            ),
          ],
        ),
      ),
    );
  }
}

If you have a more complex ThemeData file, then the same concept applies but you have to store each color individually, which I find is easiest to do by storing the int value of a color.如果您有一个更复杂的ThemeData文件,则适用相同的概念,但您必须单独存储每种颜色,我发现通过存储颜色的int值最容易做到这一点。

  int colorValue = Colors.red.value; // store this int

Then when restoring from storage you can use this function然后从存储中恢复时,您可以使用此 function

Color mapIntToColor(int value) {
    return Color(value);
  }

As for your language settings, same thing.至于您的语言设置,同样的事情。 Just add a Locale variable to your Getx class, store a couple strings, initialize before running the app, then pass that Locale variable into the locale field in GetMaterialApp .只需在 Getx class 中添加一个Locale变量,存储几个字符串,在运行应用程序之前进行初始化,然后将该Locale变量传递到GetMaterialApp中的 locale 字段。

It should be possible using SharedPreferences.应该可以使用 SharedPreferences。 Assign key value pairs (eg theme, dark) or (theme, light) that you can save and read and then run your logic on those to call the ThemeData when opening the app.分配您可以保存和读取的键值对(例如主题、深色)或(主题、浅色),然后在这些键值对上运行您的逻辑以在打开应用程序时调用 ThemeData。

saving:保存:

_saveTheme() async {
  final prefs = await SharedPreferences.getInstance();
  final key = 'theme';
  final value = _theme;
  prefs.setString(key, value);
 }

reading when initializing app and set theme - something like this (I did not test):在初始化应用程序和设置主题时阅读 - 像这样(我没有测试):

_readTheme(context) async {
  final prefs = await SharedPreferences.getInstance();
  final key = 'theme';
  final _theme = prefs.getString(key) ?? "light"; //set theme to light if the key is not found in SharedPreferences
  Get.changeTheme(
   _theme == 'light' ? ThemeData.light() : ThemeData.dark())
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM