【问题标题】:How to Force the user to answer a question for open the app in Flutter?如何强制用户回答问题以在 Flutter 中打开应用程序?
【发布时间】:2022-01-25 15:24:15
【问题描述】:

我有一个 Flutter 应用程序,我想添加一个在打开应用程序时出现的页面,要求用户回答一个问题,例如世界上有多少个国家 - 答案已经存储在应用程序中,所以如果答案正确,答案已存储,应用程序打开,此页面不再出现, 但是如果答案是错误的,用户仍然在这个页面上,直到他写下正确的答案,他才能打开应用程序 有什么有用的建议或例子吗?

更新:我创建了以下验证页面,检查输入的文本是否等于存储的文本,如果是,我使用flutter_secure_storage 存储文本现在我想知道如何我可以将shared_preferences 添加到我的代码中吗?

class check extends StatefulWidget {
  @override
  _checkState createState() => _checkState();
}

class _checkState extends State<check> {

  final formKey = GlobalKey<FormState>();
  final verifierController = TextEditingController();
  String storedvalue = '200';
 

  @override
  void initState() {
    super.initState();
    init();
  }

  Future init() async {
    final realcode = await UserSecureStorage.getCodestored() ?? '';

    setState(() {
      this.verifierController.text = realcode;
    });
  }

  Codecheck() async {
    await UserSecureStorage.setUsername(verifierController.text);

    if (storedvalue == verifierController.text) {
      Navigator.of(context).pushReplacementNamed('/homeScreen');
    }
    else  {
    
      Navigator.of(context).pushReplacementNamed('/checkScreen');
    }

  }

  @override
  Widget build(BuildContext context) {
  return Scaffold(
        body: Padding(
          padding: const EdgeInsets.all(10),
          child: Center(
              child: Stack(
            children: [
           Align(
                  child: Text(
                    'how many countries are there in the world?',
            .........
                ),
                Align(
                    child: TextFormField(
                      .......
                      controller: verifierController,
                    
                    )),
                Align(
                    child: RaisedButton(
                     .........
                        onPressed: () async {
                            Codecheck();
                          },
                       ..........

【问题讨论】:

  • 你尝试了什么?

标签: flutter dart


【解决方案1】:

您将检查用户的答案,如果正确,则在 shared preferences 中保存一个布尔值,然后导航到应用程序主页,每次打开应用程序时,您都会从共享首选项中检查此布尔值,如果它是true 则不显示问题直接打开主页,如果不显示则再次显示问题

【讨论】:

    【解决方案2】:

    以一种非常简单的方式,您可以使用SharedPreferences 插件来永久存储您的问题的答案,例如

    您可以存储一个“question”键,其值为“世界上有多少个国家?”(可选)。 您还存储了一个值为“324”(世界上国家的确切数量)的“answer”键

    然后您创建一个“answer_found”键,该键将是一个布尔值,如果用户正确回答问题,则会更新。

    然后在应用启动时,首先查询“answer_found”键,看其值是否为True

    如果该值为True,则不显示调查问卷页面,如果为false或null,则显示调查问卷页面。

    当用户输入答案时,只需将他的答案与首选项中“answer”键中包含的答案进行比较。如果正确,只需更新键“answer_found”即可。在相反的情况下什么都不做(或你想要的)

    更新: 如您所问,这是代码的摘录。 我让它尽可能简单(尽管它有点野蛮),以便您可以尽可能地理解该机制,并且您可以根据需要对其进行调整。

    import 'package:flutter/material.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await SharedPreferences.getInstance().then((preferences) async {
        //Optional key (and can put want you want)
        //Store the question in preferences
        await preferences.setString('question', 'how many countries are there in the world?');
    
        //Store the answer
        await preferences.setInt('answer', 324);
      });
    
      runApp(const MyApp());
    }
    
    class MyApp extends StatefulWidget {
      const MyApp({Key? key}) : super(key: key);
    
      @override
      State<MyApp> createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      bool? questionAnswered;
    
      @override
      void initState() {
        super.initState();
        _getQuestionState();
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: home,
        );
      }
    
      Widget get home {
        if (questionAnswered == null) {
          return const Scaffold(body: Center(child: CircularProgressIndicator()));
        } else if (questionAnswered!) {
          return const HomePage();
        } else {
          return const QuestionPage();
        }
      }
    
      Future<void> _getQuestionState() async {
        final preferences = await SharedPreferences.getInstance();
    
        //obtaining the present value of 'answer_found' to know if the question has been answered (with a correct answer)
        final isQuestionAnswered = preferences.getBool('answer_found') ??
            false; //if the value is null, we set it to false (to avoid a NullException)
    
        setState(() => questionAnswered = isQuestionAnswered);
      }
    }
    
    class HomePage extends StatelessWidget {
      const HomePage({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) => Scaffold(
            appBar: AppBar(
              title: const Text('Home Page'),
            ),
            body: const Center(
              child: Text('WELCOME'),
            ),
          );
    }
    
    class QuestionPage extends StatefulWidget {
      const QuestionPage({Key? key}) : super(key: key);
    
      @override
      State<QuestionPage> createState() => _QuestionPageState();
    }
    
    class _QuestionPageState extends State<QuestionPage> {
      late final TextEditingController _answerTextController;
    
      @override
      void initState() {
        super.initState();
    
        _answerTextController = TextEditingController();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                const Text('how many countries are there in the world?'),
                TextField(
                  controller: _answerTextController,
                  decoration: const InputDecoration(hintText: 'Enter answer'),
                ),
                ElevatedButton(
                    onPressed: () async {
                      //Convert the user's response to be in an integer type (because we want to make a comparison with an integer)
                      //The user's response will be null, if the user has not entered an integer
                      final userAnswer = int.tryParse(_answerTextController.text);
    
                      if (userAnswer != null) {
                        final preferences = await SharedPreferences.getInstance();
    
                        final storedAnswer = preferences.getInt('answer')!;
    
                        if (userAnswer == storedAnswer) {
                          preferences.setBool('answer_found', true);
    
                          Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => const HomePage()));
                        } else {
                          //Notify user that his answer was wrong or do some stuff (what you want)
                        }
                      } else {
                        //Do some stuff
                      }
                    },
                    child: const Text('Validate')),
              ],
            ),
          ),
        );
      }
    }
    

    我从未使用过flutter_secure_storage插件,但是按照我为您制作的代码sn-p,我认为您可以将其重新调整为使用flutter_secure存储,推理和逻辑是相同的。

    P.S:您不必同时使用 shared_preferences 和 flutter_secure_storage。你可以简单地使用flutter_secure_storage,它与shared_preferences不同,它为你提供了一个安全的存储空间(正如它的名字所示),你只需要实现相同的逻辑。

    【讨论】:

    • 非常感谢,能给我一些代码吗!
    • 我已经更新了我的问题。
    • 当然...我已经更新了我的答案
    • 再次非常感谢您的出色回答,如果可能的话,我还有最后一个问题,如果我想用另一个问题替换上一个问题-'世界上有多少个国家?-比如你的手机品牌是什么?答案是提前使用插件device_info提取的,知道自己试过了,没有得到任何结果
    • 谢谢它的作品。
    【解决方案3】:

    我希望您将启动屏幕作为您的应用程序中加载的第一个屏幕。

    现在,当第一个屏幕加载时。 使第一个屏幕成为有状态的。

    这将允许您使用“initstate”方法。并且你知道会首先调用initstate方法来执行代码。

    
    initstate(){
     /// in this case I am using "get_storage" to store the data in local.
     GetStorage prefs = GetStorage("ApplicationName");
     bool isAnswered = prefs.read("isAnsweredQuestion") ?? false;
     if(isAnswered){
      /// redirect to the other screen.
     }else{
      /// redirect to the screen where you have the questions
      /// or open the dialog having questions.
     }
     super.initstate();
    };
    
    

    initstate 方法将在应用程序加载并执行启动画面时第一次执行,它会检查本地数据存储。

    如果用户是第一次打开应用程序,那么本地数据将为空,我们使用空检查运算符来处理。

    如果用户已经回答了问题,那么我们将在本地存储“true”。在这种情况下,我们会将用户重定向到另一个屏幕。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-26
      • 2021-11-08
      • 2022-11-12
      • 1970-01-01
      • 1970-01-01
      • 2021-10-07
      • 2019-01-20
      • 2019-03-08
      相关资源
      最近更新 更多