- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在为我女儿开发一个简单的数学应用程序。下面是一些您可以根据需要使用的代码(它可能不是最漂亮的代码,但它工作正常并且可能对某些人有帮助)。
我的问题是:
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/
我有一个测试即将进行,我想澄清两个有关参数的问题。 在我的笔记中指出,将参数传递给函数的推荐方法是使用“按引用传递” const type& x; // for "in" parameters
当我通过 OMG 2.5(Beta)推广的 UML 规范阅读以下概念时: in: Indicates that Parameter values are passed in by the caller
我试图在用户按下 Enter 时触发一个函数。我将此输入设置为只读的原因是限制用户在填充值后修改输入中的值。 该值来自将在点击属性中触发的弹出窗口。问题是 keyup.enter 没有触发该输入。 代
我在jQuery中使用模式弹出窗口控件,该弹出窗口具有由jQuery Tokenize输入插件提供动力的输入文本。问题是,当我在模式弹出文本框中键入内容时, token 化插件的搜索结果显示为隐藏在弹
我有一个问题。当我选中复选框时,系统工作正常,总值发生变化,但一旦我修改文本输入,它就会变为 0。我需要将此文本框输入排除在更改值之外。 这是 html: $15000 $
我正在努力让它发挥作用,但还是有些不对劲。 我想用 CSS 设置提交按钮的样式以匹配我已有的按钮。 风格: input[type="button"], input[type="submit"], b
import java.util.*;; public class selection { Scanner in=new Scanner(System.in); private
这可能是一个非常菜鸟的问题。假设我有一个带宽限制为 100MB/s 的网卡,那么输入/输出带宽是否有可能达到该限制 同时 ?或者我会在任何时候遇到这个不等式:in bandwidth + out ba
看着这个问题,Fill immutable map with for loop upon creation ,我很好奇是什么this表示在 Map(1 -> this) . scala> Map(1
我有这样的东西 一个 乙 问? 是或否 数字 数字或零 我想做的是: 如果 B1 = “Y”,则让用户在 B2 中输入一个数字。 如果 B1 = “N”,则将 B2 中的值更改为零,并且不允许用户在
我有一个包含许多列的表,我想添加 input标题单元格内的字段,但我希望输入适合根据正文内容的宽度。 这是没有 input 的样子领域: 这就是 input 的样子领域: 可以看出,像“index”和
关于为 FTP 客户端设置传出和传入文件夹,您遵循哪些最佳实践(如果有)?我们通常使用“outgoing”和“incoming”,但无论你如何表述方向,它都可以有两种解释方式,具体取决于名称相对于哪一
我正在尝试“求解”给定 d 的 Pell 方程:x^2 - d * y^2 = 1,或者至少我想得到最小的 x > 0 来求解方程。到目前为止,一切都很好。这是我的 Haskell 代码 minX :
我是VS Code的新手,可以使用Ctrl + Enter将代码运行到python交互式窗口中。我希望光标自动移动到下一行,因此我可以逐行浏览代码。 能做到吗? 最佳答案 如this blog pos
我正在创建一个 bool 值矩阵/二维数组,并且我想为 dategrid 推断一种不仅仅是“ANY”的类型。 let yearRange = [2000,2001,2002,2003,2004]; l
我有两个排序的列表,例如 a = [1, 4, 7, 8] b = [1, 2, 3, 4, 5, 6] 我想知道a中的每个项目是否在b中。对于上面的示例,我想找到 a_in_b = [True, T
菜鸟警报 这很奇怪 - 当我编写以下代码时,尝试在 AngularJS 中创建自定义指令: myModule.directive('myTab', function(){ console.lo
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
假设我正在使用 gdscript 静态类型,并且对于一个函数参数,我事先不知道我会得到什么。这就是 python 中 typing.Any 的作用。如何使用 gdscript 做到这一点? 似乎 Va
我使用 dropzone 上传多个图像,并且工作正常,直到我想为每个图像插入品牌和网址。 我遇到的唯一问题是,当我要从输入字段获取值时,我会从服务器获取来自字段(品牌、网址)的未定义值,但如果我使用静
我是一名优秀的程序员,十分优秀!