【问题标题】:Enable & Disable a button using ternary operators使用三元运算符启用和禁用按钮
【发布时间】:2022-01-08 09:45:11
【问题描述】:

当布尔值变为真时,我试图激活一个按钮。我有一个类,它包含一个设置为假的布尔值。 然后我有一个自定义小部件,其中有一个最终布尔值,当我在主应用程序中调用小部件时,我将其设置为 true。当最终的布尔值为真时,我将类中的布尔值设置为真。然后我在按钮上使用三元运算符。我想做的是当用户回答最后一个问题时,应该启用提交按钮。 即使类 bool 设置为 true,按钮也不会激活。如果我刷新页面,按钮就会激活。我认为这是一个国家问题

附:我删除了一些不必要的代码。

成绩等级

class Score {
  static int score = 0;
  
  static bool allQuestionsAnswered = false; //THIS VARIABLE WILL BE CHANGED BASED ON THE FINAL VARIABLE
}

带有提交按钮的主小部件

class Quiz extends StatefulWidget {
  const Quiz({Key? key}) : super(key: key);

  @override
  _QuizState createState() => _QuizState();
}

class _QuizState extends State<Quiz> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          leading: IconButton(
            icon: Icon(Icons.arrow_back_rounded),
            onPressed: () {
              var route = ModalRoute.of(context);
              var name = route?.settings.name;

              if (name == null) {
                Score.score = 0;
                Navigator.push(context,
                    MaterialPageRoute(builder: (context) => Homepage()));
              }
            },
          ),
          title: const Text('CyberQuiz'),
        ),
        body: SingleChildScrollView(
            scrollDirection: Axis.vertical,
            child: Column(
              children: [
                Text('Score: ' + Score.score.toString()),
                SizedBox(
                  height: 150,
                ),
                Text(
                  'Online Behaviour Questions',
                  style: TextStyle(
                    fontSize: 35,
                    color: Colors.white,
                  ),
                ),
                SizedBox(
                  height: 20,
                ),
                Text(
                  'Scale based answers, Strongly Disagree (1) to Agree (5)',
                  style: TextStyle(
                    fontSize: 20,
                    color: Colors.white,
                  ),
                ),
                SizedBox(
                  height: 50,
                ),
                OnlineBehaviour(
                    '6. I tend to use similar passwords for multiple accounts',
                    'Using the same password accross all online accounts, users give '
                        'hackers easy access to their whole digital life. It is like leaving '
                        'the keys under the doormat. If a hacker gains access to one user account,'
                        ' he or she can easily take over all online account and impersonate them',
                    false),
                SizedBox(
                  height: 80,
                ),
                OnlineBehaviour(
                    '7. I like posting stuff on social media to socialise with my friends',
                    'While it may seem like'
                        'the information is being share with your friends and family,'
                        'it can also be share with hackers and scammers who troll the social media sites',
                    false),
                SizedBox(
                  height: 80,
                ),
                OnlineBehaviour(
                    '8. I have a lot of accounts, thus I am using a notebook to write them down',
                    'Anyone can take your notebook '
                        'and access all of your personal data including bank account credentials'
                        '.There are many programs out there that act as a safe "journal for passwords"',
                    false),
                SizedBox(
                  height: 80,
                ),
                OnlineBehaviour(
                    '9. I tend to ignore requests from apps to access my location, files, camera etc.',
                    'Ignoring these requests might be very dangerous'
                        "as many online predators are in a continuous hunt of new people's location and their personal data."
                        'E.g. They can check whether your are home or not and they can schedule a potential robbery',
                    false),
                SizedBox(
                  height: 80,
                ),
                OnlineBehaviour(
                    '10. I accept all terms & conditions of all apps/websites without reading them',
                    'All of us are guilty for this one because a lot of websites/apps have loads of pages '
                        'talking about their conditions when accessing their services. If you ignore these they might'
                        'use the data stored on you in bad ways such as selling it to other '
                        'dodgy companies who might use your data in malicious ways',
                    true), //THIS IS WHERE I SET THE FINAL VARIABLE TO TRUE
                ElevatedButton(
                    style: ButtonStyle(
                        backgroundColor:
                            MaterialStateProperty.all(Colors.orange)),
                    onPressed: Score.allQuestionsAnswered == true //THIS IS WHERE I USED TERNARY OPERATOR
                        ? () {
                            showDialog(
                                barrierDismissible: false,
                                context: context,
                                builder: (BuildContext context) {
                                  return AlertDialog(
                                    title: Text('Well done!'),
                                    content: Text(
                                        'Score: ' + Score.score.toString()),
                                    elevation: 24.0,
                                    shape: RoundedRectangleBorder(),
                                    actions: [
                                      TextButton(
                                          onPressed: () {
                                            Navigator.push(
                                                context,
                                                MaterialPageRoute(
                                                    builder: (context) =>
                                                        Homepage()));
                                          },
                                          child: Text('OK'))
                                    ],
                                  );
                                });
                          }
                        : null,
                    child: Text('Submit'))
              ],
            )));
  }
}

自定义小部件

class OnlineBehaviour extends StatefulWidget {
  final String behaviourQuestion;
  final String explanation;
  final bool lastQuestionAnswered;

  bool buttonTapped = false;

  bool questionsAnswered = false;

  OnlineBehaviour(
    this.behaviourQuestion,
    this.explanation,
    this.lastQuestionAnswered,
  );

  @override
  _OnlineBehaviourState createState() => _OnlineBehaviourState();
}

class _OnlineBehaviourState extends State<OnlineBehaviour> {
  disableButton() {
    setState(() {
      widget.questionsAnswered = true;
    });
  }

  activateSubmitButton() {
    setState(() {
      if (widget.lastQuestionAnswered == true) {
        Score.allQuestionsAnswered = true;  //FUNCTION THAT SETS THE BOOL IN THE SCORE CLASS TO TRUE
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(
          widget.behaviourQuestion,
          style: TextStyle(fontSize: 30, color: Colors.white),
        ),
        SizedBox(
          height: 20,
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            ElevatedButton(
                style: ButtonStyle(
                    backgroundColor:
                        MaterialStateProperty.all(Color(0xFF45687b))),
                onPressed: widget.questionsAnswered == false
                    ? () {
                        setState(() {
                          Score.score += 5;
                          activateSubmitButton();
                          widget.buttonTapped = true;
                        });
                        if (widget.buttonTapped == true) {
                          disableButton();

                          print(Score.allQuestionsAnswered);
                        }
                      }
                    : null,
                child: Text(
                  '1',
                  style: TextStyle(
                    color: Color(0xFFe5e0e4),
                    fontSize: 15,
                    fontWeight: FontWeight.bold,
                  ),
                )),

【问题讨论】:

  • 您面临的问题是什么?
  • 当 bool 为 true 时,提交按钮不会激活,它保持禁用状态

标签: flutter flutter-web


【解决方案1】:

我猜问题是即使您更新了静态类的值,按钮仍然处于禁用状态。

如果这是问题所在,那么可能不是因为您没有更改值,或者因为您的三元运算符错误,而仅仅是因为您没有告诉主小部件检查静态类的值再次。为此,您应该更改 setState 方法中的值(您可以这样做,但您使用自定义小部件的 setState 方法来完成此操作,该方法不会更新主小部件)。

有很多方法可以尝试改变这一点,但我要做的是为您的自定义小部件声明一个新参数onAllQuestionsAnswered

在自定义小部件上

  final String behaviourQuestion;
  final String explanation;
  final bool lastQuestionAnswered;
  final VoidCallback onAllQuestionsAnswered; // <--

那么当你设置静态类的值时,你可以这样做:

if (widget.lastQuestionAnswered == true) {
  onAllQuestionsAnswered();
}

最后,在您的主小部件上,您将传递此回调:

OnlineBehaviour(
...
onAllQuestionsAnswered: () => setState(() =>Score.allQuestionsAnswered = true),
);

一般来说,您也可以完全摆脱静态变量,只将状态存储在主小部件上,但这超出了此答案的范围。

【讨论】:

  • 非常感谢,我将如何删除静态变量。只是出于好奇:D
  • 基本思想是将所有变量作为实例成员移动到主窗口小部件中,然后像我们为 OnlineBehaviour 类上的allQuestionsAnswered 所做的那样使用回调传递它们并编辑它们,希望这使得感觉:)?
  • 是的,谢谢
【解决方案2】:

问题就在这里,您在Quiz 小部件上的按钮,但您正在更新OnlineBehaviour 小部件状态,这就是ui 没有更新的原因,我建议您使用state-management,现在您可以使用回调方法这个。

在您的 OnlineBehaviour 上,我正在添加另一个可为空的回调函数,这样您就可以只使用一次并避免其余部分

class OnlineBehaviour extends StatefulWidget {
  final String behaviourQuestion;
  final String explanation;
  final bool lastQuestionAnswered;

  final Function? callBack;

  bool buttonTapped = false;

  bool questionsAnswered = false;

  OnlineBehaviour(
    this.behaviourQuestion,
    this.explanation,
    this.lastQuestionAnswered, {
    this.callBack = null,
  });

然后在 onpress 上调用它

  
     onPressed: widget.questionsAnswered == false
                    ? () {
                        if (widget.callBack != null) {  // -<this
                          widget.callBack!();
                        }
                        setState(() {
                          Score.score += 5;
                          activateSubmitButton();
                          widget.buttonTapped = true;
                        });
                        if (widget.buttonTapped == true) {
                          disableButton();

                          print(Score.allQuestionsAnswered);
                        }
                      }
                    : null,

仅针对您想更新 UI 的最后一个问题使用它

    OnlineBehaviour(
                  '10. I accept all terms & conditions of all apps/websites without reading them',
                  'All of us are guilty for this one because a lot of websites/apps have loads of pages '
                      'talking about their conditions when accessing their services. If you ignore these they might'
                      'use the data stored on you in bad ways such as selling it to other '
                      'dodgy companies who might use your data in malicious ways',
                  true,
                  callBack: () {
                    setState(() {});
                  },
                ), //THIS Is

【讨论】:

    【解决方案3】:

    问题不在于更新“allQuestionsAnswered”的布尔值。 您面临的问题是您需要在初始化主小部件后更新您的 UI。 您可以通过将其添加到您的主小部件来实现这一点,不需要来自另一个类的回调:

        void initState() {
            super.initState();
            WidgetsBinding.instance
                .addPostFrameCallback((_) => 
       setState(() {});
          }
    

    此代码将确保您的小部件在完成初始化后获得额外的 UI 更新。

    【讨论】:

      猜你喜欢
      • 2019-07-08
      • 1970-01-01
      • 2014-11-07
      • 2015-10-24
      • 1970-01-01
      • 2012-02-17
      • 1970-01-01
      • 2020-03-14
      相关资源
      最近更新 更多