【问题标题】:Flutter: Storing language and theme preference when using GetX utility functionsFlutter:使用 GetX 实用程序函数时存储语言和主题偏好
【发布时间】:2021-03-11 16:57:33
【问题描述】:

在使用 GetX 的实用程序功能时,有什么方法可以存储用户偏好(并在重新启动时检索它们):

Get.changeTheme(ThemeData().dark)

还有

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

到目前为止,我只能更改主题和语言,但我还没有在 GetX 中找到一种方法来坚持对任何类型的存储进行任何更改,以便下次重新打开应用程序时加载。有什么我忽略的吗?有什么方法可以挂接到启动过程并检查一些存储的值(例如在SharedPreferences 中)并将它们传递给我在GetMaterialApp 中的localetheme 属性?

这是我的代码:

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

【问题讨论】:

    标签: flutter flutter-getx


    【解决方案1】:

    使用GetStorage 更容易做到这一点。

    如果您只是从浅色主题更改为深色主题,则每次更改主题时都存储一个简单的布尔值。

    这是使用基本设置类执行此操作的一种方法。

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

    SettingsController 类中的 themeData 变量根据存储中的布尔值进行初始化。 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(),
        );
      }
    }
    

    然后在运行您的应用之前将这两行都放入您的 Main 方法中。

      await GetStorage.init();
    
      Get.put(SettingsController());
    

    这是一个演示页面,您可以在其中进行测试。

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

    如果您有一个更复杂的ThemeData 文件,那么同样的概念也适用,但您必须单独存储每种颜色,我发现通过存储颜色的int 值最容易做到这一点。

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

    那么在从存储中恢复的时候就可以使用这个功能了

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

    至于您的语言设置,同样的事情。只需将Locale 变量添加到您的Getx 类,存储几个字符串,在运行应用程序之前进行初始化,然后将该Locale 变量传递到GetMaterialApp 的区域设置字段中。

    【讨论】:

      【解决方案2】:

      应该可以使用 SharedPreferences。分配可以保存和读取的键值对(例如主题、深色)或(主题、浅色),然后在它们上运行逻辑以在打开应用程序时调用 ThemeData。

      保存:

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

      在初始化应用程序和设置主题时阅读 - 类似这样(我没有测试):

      _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())
      }
      

      【讨论】:

      • 好的,您能否提供一些代码示例,使用我在上面发布的代码来说明您将如何“在打开应用程序时调用 ThemeData”?
      • 我编辑了我的答案以展示我会在你的情况下做什么 - 你需要进行一些试验并在需要的地方进行微调
      猜你喜欢
      • 2021-07-18
      • 2012-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-09
      • 2021-02-14
      • 2016-06-17
      • 2015-05-30
      相关资源
      最近更新 更多