草庐IT

function - 输入长度和按钮点击的问题

coder 2023-07-24 原文

我正在为我女儿开发一个简单的数学应用程序。下面是一些您可以根据需要使用的代码(它可能不是最漂亮的代码,但它工作正常并且可能对某些人有帮助)。

我的问题是:

1) 限制用户可以输入的字符(数字)的数量。我只在涉及到 textFields(例如 maxLength)时才找到解决方案。

2) 我的刷新按钮(“下一步”)根本不起作用。这个想法是从之前的算术选择中给用户一个新的随机数学任务。

3) 目前您可以输入错误的答案,单击确定,然后更正您的答案以获得“正确”。计划是,一旦您单击确定,您将无法更改您的答案。您将只能单击“下一步”。 (我计划稍后对此实现一个计数器,它将在 x 个任务后返回正确和错误答案的数量)。

非常感谢任何帮助(代码或我将查看的内容)。谢谢。

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
      .then((_) => runApp(HomePage()));
}

class HomePage extends StatelessWidget {
   @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'input',
      theme: ThemeData(primarySwatch: Colors.purple),
      home: FirstClass(),
    );
  }
}

 class FirstClass extends StatefulWidget {
  @override
  _FirstClassState createState() => _FirstClassState();
}

class _FirstClassState extends State<FirstClass> {
  final random = Random();
  int a, b, c, sum;
  String output;

  void changeData(String buttonName) {
    setState(() {
      a = random.nextInt(10);
      b = random.nextInt(10);

      if (buttonName == '+') {
         sum = a + b;
        output = '$a+$b= ';
      } else if (buttonName == '-') {
        if (a >= b) {
          sum = a - b;
          output = '$a-$b= ';
        } else if (b > a) {
          sum = b - a;
          output = '$b-$a= ';
        }
      }

      print(sum.toString());
      Navigator.of(context).popUntil(ModalRoute.withName('/'));
      Navigator.of(context).push(MaterialPageRoute(
          builder: (context) => SecondClass(
                sum: sum,
                refresh: changeData,
                output: output,
                buttonName: buttonName,
              )));
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(color: Colors.deepPurple),
      child: Scaffold(
        backgroundColor: Colors.transparent,
        appBar: AppBar(
          centerTitle: true,
          backgroundColor: Colors.transparent,
          elevation: 0.0,
          leading: IconButton(
            icon: Icon(Icons.menu),
            onPressed: () {},
          ),
          title: Text(
            'MATH',
            style: TextStyle(fontSize: 25.0),
          ),
        ),
        body: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              RaisedButton(
                  child: Text('+', style: TextStyle(fontSize: 24.0)),
                  onPressed: () => changeData('+')),
              RaisedButton(
                   child: Text('-', style: TextStyle(fontSize: 24.0)),
                  onPressed: () => changeData('-')),
            ],
          ),
        ),
      ),
    );
  }
}

class SecondClass extends StatefulWidget {
  final int sum;
  final String output;
  final String buttonName;
  final Function refresh;

  SecondClass({this.sum, this.refresh, this.buttonName, this.output});

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

class _SecondClassState extends State<SecondClass> {
  String output = "";
  String _output = "";
  String output2 = "";

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

  buttonPressed(String buttonText) {
    if (buttonText == "<-") {
      _output = "";
    } else if (buttonText == "OK") {
      if (output.isNotEmpty) {
        if (output == widget.sum.toString()) {
          setState(() {
            output2 = 'Correct';
          });
        } else {
          setState(() {
            output2 = 'False';
          });
        }
      } else if (buttonText == "NEXT") {
        widget.refresh(widget.buttonName);
      }
    } else {
      _output = _output + buttonText;
    }
    setState(() {
      output = _output;
    });
    print(buttonText);
  }

  Widget buildButton(String buttonText) {
    return Expanded(
      child: Padding(
        padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0),
        child: OutlineButton(
            color: Colors.white,
            child: Text(
              buttonText,
              style: TextStyle(
                  color: Colors.white,
                  fontSize: 20.0,
                  fontWeight: FontWeight.bold),
            ),
            onPressed: () => buttonPressed(buttonText)),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(color: Colors.purple),
      child: Column(
        children: <Widget>[
          Padding(
            padding: const EdgeInsets.only(top: 40.0, left: 20.0, right: 
20.0),
            child: Container(
                height: 60.0,
                width: double.infinity,
                decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(15.0)),
                child: Center(
                  child: Text(
                    widget.output + output,
                    style: TextStyle(
                        color: Colors.black,
                        fontSize: 48.0,
                        fontWeight: FontWeight.bold),
                  ),
                )),
          ),
          Padding(
            padding: const EdgeInsets.only(top: 20.0, left: 20.0, right: 
20.0),
            child: Container(
               height: 60.0,
              width: double.infinity,
              decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(15.0)),
              child: Text(
                output2,
                style: TextStyle(
                    color: Colors.black,
                    fontSize: 48.0,
                    fontWeight: FontWeight.bold),
              ),
            ),
          ),
          Expanded(child: Divider()),
           Column(
            children: <Widget>[
              Row(
                children: <Widget>[
                  buildButton('1'),
                  buildButton('2'),
                  buildButton('3'),
                ],
              ),
              Row(
                children: <Widget>[
                  buildButton('4'),
                  buildButton('5'),
                  buildButton('6'),
                ],
              ),
              Row(
                children: <Widget>[
                  buildButton('7'),
                  buildButton('8'),
                  buildButton('9'),
                ],
              ),
              Row(
                children: <Widget>[
                  buildButton('<-'),
                  buildButton('0'),
                  buildButton('OK'),
                ],
              ),
              Row(
                children: <Widget>[
                  buildButton('NEXT'),
                ],
              ),
            ],
           ),
        ],
       ),
    );
  }
}

最佳答案

很好,它正在工作。这不是执行此操作的最佳方法,但我尝试保留您的旧代码库。我真的建议使用 BLoC 等模式来管理小部件的状态并避免调用 setState。

需要将您的代码拆分到更多类中。 我在这里做了什么??

  • 创建一个名为 MathOperation 的枚举。此枚举用于标识用户选择了哪种算术运算。

  • 旧的 FirstClass 现在是 OperationSelectorScreen

  • 旧的 SecondClass 现在是 QuestionAndAnswerScreen

  • 我创建了 CustomTextField 类来实现具有最大字符数的简单“文本字段”。

  • 我已经实现了 MathOperationTask 类。此类是算术运算(如加法和减法)的抽象。该类保存了参与运算的数字,他的符号“+”或“-”以及运算结果。

源代码中有一些注释可以指导您,如果您需要提出任何问题,请随时做,我会尽可能回答。希望对您有所帮助。

import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

/// enum used to identify math operation types
enum MathOperation { SUM, SUBTRACTION }

void main() {
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
      .then((_) => runApp(HomePage()));
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'input',
      theme: ThemeData(primarySwatch: Colors.purple),
      home: OperationSelectorScreen(),
    );
  }
}

/// old FirstClass
class OperationSelectorScreen extends StatefulWidget {
  @override
  _OperationSelectorScreenState createState() => _OperationSelectorScreenState();
}

class _OperationSelectorScreenState extends State<OperationSelectorScreen> {

  MathOperation _userSelectedOperation;

  void changeData(String buttonName) {
    setState(() {
      if (buttonName == '+') {
        _userSelectedOperation = MathOperation.SUM;
      } else if (buttonName == '-') {
        _userSelectedOperation = MathOperation.SUBTRACTION;
      }

      Navigator.of(context).popUntil(ModalRoute.withName('/'));

      /// we only need pass to next screen what kind of operation
      /// was selected by user
      Navigator.of(context).push(MaterialPageRoute(
          builder: (context) => QuestionAndAnswerScreen(
            operationType: _userSelectedOperation,// operation selected by user  ( '+' or '-' )
          )));
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: BoxDecoration(color: Colors.deepPurple),
      child: Scaffold(
        backgroundColor: Colors.transparent,
        appBar: AppBar(
          centerTitle: true,
          backgroundColor: Colors.transparent,
          elevation: 0.0,
          leading: IconButton(
            icon: Icon(Icons.menu),
            onPressed: () {},
          ),
          title: Text(
            'MATH',
            style: TextStyle(fontSize: 25.0),
          ),
        ),
        body: Center(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[

              RaisedButton(
                  child: Text('+', style: TextStyle(fontSize: 24.0)),
                  onPressed: () => changeData('+')),

              RaisedButton(
                  child: Text('-', style: TextStyle(fontSize: 24.0)),
                  onPressed: () => changeData('-')),
            ],
          ),
        ),
      ),
    );
  }
}

/// old SecondClass
class QuestionAndAnswerScreen extends StatefulWidget {
  final operationType; // if the operations will be (+) or (-)

  QuestionAndAnswerScreen({this.operationType});

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

class _QuestionAndAnswerScreenState extends State<QuestionAndAnswerScreen> {

  String _userTypedAnswer=""; // numbers that user had typed
  String _answerValidationOutput = ""; // will say if the user answer ir correct or wrong(false)
  MathOperationTask _currentTask; // current arithmetic operation

  // this member controls the back button "<-" activity
  // if user had responded the question, this value will be true and
  // the button "<-" will not work properly.
  bool _isQuestionResponded = false;

  @override
  void initState() {
    super.initState();
    //using math operation task generator method to create a new math operation
    _currentTask = MathOperationTask.generateMathTask( widget.operationType );
  }

  buttonPressed(String buttonText) {
    // this logic can be improved if we
    // transform the custom keyboard in a widget

    if (buttonText == "<-") {
      if (!_isQuestionResponded){
        _changeUserTypedText("");
        _changeAnswerValidationText("");
      }
    }

    else if (buttonText == "OK") {
      if (_userTypedAnswer.isNotEmpty) {
        _isQuestionResponded = true;
        if (_userTypedAnswer == _currentTask.results.toString()) {
          _changeAnswerValidationText('Correct');
        }

        else {
          _changeAnswerValidationText('False');
        }
      }
    }

    else if (buttonText == "NEXT") {
      print("new OP");
      _spawnArithmeticOperation();
    }

    else {
      ///This if statement solves the problem of put in member after question
     ///responded.If question is NOT responded, OK button not pressed then we update the text. 
     if (!_isQuestionResponded)
        _changeUserTypedText( (_userTypedAnswer + buttonText) );
    }

  }

  /// this mehtod creates a new arithmetic operation and update the screen with
  void _spawnArithmeticOperation(){
    _currentTask = MathOperationTask.generateMathTask(widget.operationType);
    _answerValidationOutput ="";
    _userTypedAnswer = "";
    _isQuestionResponded = false;
    setState(() {});
  }

  /// method to change and update UI after user type something.
  void _changeUserTypedText(String text){
    setState(() => _userTypedAnswer = text );
  }

  /// update the text if the answer is correct, wrong or clean the text.
  void _changeAnswerValidationText(String text){
    setState(() => _answerValidationOutput = text );
  }

  Widget buildButton(String buttonText) {
    return Expanded(
      child: Padding(
        padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0),
        child: OutlineButton(
            color: Colors.white,
            child: Text(
              buttonText,
              style: TextStyle(
                  color: Colors.white,
                  fontSize: 20.0,
                  fontWeight: FontWeight.bold),
            ),
            onPressed: () => buttonPressed(buttonText)),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {

    final operationField = CustomTextField( maxLength: 7, // max text length
      text: "${_currentTask.firstMember}" // first member of operation
          "${_currentTask.operationSymbol}" // operation signal
          "${_currentTask.secondMember}= " // second member of math operation
          "$_userTypedAnswer",
    );

    final answerFinalResultsField = CustomTextField(
        maxLength: 7,
        text: _answerValidationOutput
    );

    return Container(
      decoration: BoxDecoration(color: Colors.purple),
      child: Column(
        children: <Widget>[
          operationField,
          answerFinalResultsField,
          Expanded(child: Divider()),
          _buildKeyboard(),
        ],
      ),
    );
  }

  // here i put your keyboard layout..
  Widget _buildKeyboard(){
    return Column(
      children: <Widget>[
        Row(
          children: <Widget>[
            buildButton('1'),
            buildButton('2'),
            buildButton('3'),
          ],
        ),
        Row(
          children: <Widget>[
            buildButton('4'),
            buildButton('5'),
            buildButton('6'),
          ],
        ),
        Row(
          children: <Widget>[
            buildButton('7'),
            buildButton('8'),
            buildButton('9'),
          ],
        ),
        Row(
          children: <Widget>[
            buildButton('<-'),
            buildButton('0'),
            buildButton('OK'),
          ],
        ),
        Row(
          children: <Widget>[
            buildButton('NEXT'),
          ],
        ),
      ],
    );
  }
}

/// this class represents an arithmetic operation
/// example 3 + 6 = 9
/// 3 is the firstMember, 6 the secondMember and results is 9.
class MathOperationTask {
  final firstMember;
  final secondMember;
  final results; //operation results
  final operationSymbol;

  // text math symbols constants only to show...
  static final String PLUS = "+";
  static final String LESS = "-";

  MathOperationTask( {this.firstMember, this.secondMember, this.results, this.operationSymbol} );

  /// this method is used to generate a specific math task from a specific type.
  static MathOperationTask generateMathTask( MathOperation type ){
    var random = Random();
    var firstMember = random.nextInt(10);// 0..9
    var secondMember = random.nextInt(10);

    switch(type){
      case MathOperation.SUM:
        return MathOperationTask(
          firstMember: firstMember,
          secondMember: secondMember,
          results: (firstMember + secondMember),
          operationSymbol: PLUS
        );

      case MathOperation.SUBTRACTION:
        var results;

        if (firstMember < secondMember) {
          // we exchange the values position in operation...
          var temp = firstMember;
          firstMember = secondMember;
          secondMember = temp;
        }

        results = firstMember - secondMember;

        return MathOperationTask(
          results: results,
          secondMember: secondMember,
          firstMember: firstMember,
          operationSymbol: LESS,
        );

      default:
        break;
    }

    //in case of invalid operation...
    return MathOperationTask(
      firstMember: 0,
      secondMember: 0,
      results: 0,
    );
  }
}

/// A simple custom text field that limits his text
/// with a specific characters number
///
class CustomTextField extends StatelessWidget {
  final maxLength;
  final _text;

  CustomTextField({this.maxLength = 7, String text}) :
      _text = (text.length > maxLength) ? text.substring(0, maxLength ) : text;
      /// this lines solves characters numbers problem
      ///if the text contains more characters that is allowed (maxLength) then we
      /// cut the string form character 0 until last position allowed (maxLength).

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: 40.0, left: 20.0, right: 20.0),
      child: Container(
        height: 60.0,
        width: double.infinity,
        decoration: BoxDecoration(
            color: Colors.white,
            borderRadius: BorderRadius.circular(15.0)),
        child: Center(
          child: Text(
            _text,
            style: TextStyle(
                color: Colors.black,
                fontSize: 48.0,
                fontWeight: FontWeight.bold),
          ),
        ),
      ),
    );

  }
}

关于function - 输入长度和按钮点击的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54855519/

有关function - 输入长度和按钮点击的问题的更多相关文章

  1. ruby-on-rails - unicode 字符串的长度 - 2

    在我的Rails(2.3,Ruby1.8.7)应用程序中,我需要将字符串截断到一定长度。该字符串是unicode,在控制台中运行测试时,例如'א'.length,我意识到返回了双倍长度。我想要一个与编码无关的长度,以便对unicode字符串或latin1编码字符串进行相同的截断。我已经了解了Ruby的大部分unicode资料,但仍然有些一头雾水。应该如何解决这个问题? 最佳答案 Rails有一个返回多字节字符的mb_chars方法。试试unicode_string.mb_chars.slice(0,50)

  2. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  3. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  4. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  5. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  6. ruby - Fast-stemmer 安装问题 - 2

    由于fast-stemmer的问题,我很难安装我想要的任何ruby​​gem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=

  7. ruby - 匹配大写字母并用后续字母填充,直到一定的字符串长度 - 2

    我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种

  8. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  9. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  10. ruby-on-rails - 简单的 Ruby on Rails 问题——如何将评论附加到用户和文章? - 2

    我意识到这可能是一个非常基本的问题,但我现在已经花了几天时间回过头来解决这个问题,但出于某种原因,Google就是没有帮助我。(我认为部分问题在于我是一个初学者,我不知道该问什么......)我也看过O'Reilly的RubyCookbook和RailsAPI,但我仍然停留在这个问题上.我找到了一些关于多态关系的信息,但它似乎不是我需要的(尽管如果我错了请告诉我)。我正在尝试调整MichaelHartl'stutorial创建一个包含用户、文章和评论的博客应用程序(不使用脚手架)。我希望评论既属于用户又属于文章。我的主要问题是:我不知道如何将当前文章的ID放入评论Controller。

随机推荐