gpt4 book ai didi

flutter - 将数据从自定义小部件文本字段传递到计算器 flutter

转载 作者:行者123 更新时间:2023-12-03 04:21:32 25 4
gpt4 key购买 nike

我试图将数据从包含文本字段的自定义窗口小部件传递到计算器窗口小部件。我面临的问题是我希望利用自定义窗口小部件创建可以输入计算器的多个输入(即高度和体重)。任何人都可以使用自定义窗口小部件协助传递数据吗?
自定义文本字段小部件已创建

import 'package:auto_size_text/auto_size_text.dart';

enum Units { unit1, unit2 }

class InputRow extends StatefulWidget {
InputRow({this.inputParameter, this.unit1, this.unit2});
final String inputParameter;
final String unit1;
final String unit2;

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

class _InputRowState extends State<InputRow> {
String newTaskTitle;
Units selectedUnit;
String unit;

@override
void initState() {
super.initState();
setState(() {
unit = widget.unit1;
});
}

@override
Widget build(BuildContext context) {
return Container(
constraints: BoxConstraints(maxWidth: 375, maxHeight: 50),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: AutoSizeText(
widget.inputParameter,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
),
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.red,
width: 3,
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
bottomLeft: Radius.circular(10),
),
),
child: TextField(
autofocus: true,
textAlign: TextAlign.center,
onChanged: (newText) {
newTaskTitle = newText;
},
),
),
),
Container(
decoration: BoxDecoration(
color: Colors.red,
border: Border.all(
color: Colors.red,
width: 3,
),
borderRadius: BorderRadius.only(
topRight: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
child: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(5),
child: Center(
child: AutoSizeText(
unit,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
)),
),
Container(
constraints: BoxConstraints(maxHeight: 50, maxWidth: 60),
child: FlatButton(
highlightColor: Colors.transparent,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.loop,
size: 25,
),
],
),
onPressed: () {
setState(() {
selectedUnit = selectedUnit == Units.unit2
? Units.unit1
: Units.unit2;
if (selectedUnit == Units.unit1) {
unit = widget.unit1;
} else {
unit = widget.unit2;
}
});
},
)),
],
),
),
],
),
);
}
}
屏幕调用小部件,并希望将在文本字段中输入的高度和体重传递给计算器



class InputScreen extends StatefulWidget {
static const String id = 'adjustments';
@override
_InputScreenState createState() =>
_AdjustmentInputScreenState();
}

class AdjustmentInputScreenState
extends State<AdjustmentInputScreen> {

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: kActiveButtonColor,
body: Column(
children: <Widget>[
AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
Navigator.pop(context);
}),
],
title: Text('Dose Adjustment'),
backgroundColor: Colors.transparent,
elevation: 0.0,
),
InputRow(
unit1: 'cm',
unit2: 'inches',
inputParameter: 'height',
),
InputRow(unit1: 'lbs', unit2: 'kg', inputParameter: 'weight',),
RoundedButton(
title: 'Calculate',
onPressed: () {
//- code needed to pass the custom textfield widget data
},
),
],
),
);
}
}
计算器大脑
import 'dart:math';

class CalculatorTest {
CalculatorTest({this.height, this.weight, this.heightUnit, this.weightUnit});

double height;
double weight;
final String heightUnit;
final String weightUnit;

double _bmi;

String calculateBMI() {
if (weightUnit == 'lbs') {
weight = weight / 2.2;
} else {
weight = weight;
}

if (heightUnit == 'inches') {
height = height / 2.53;
} else {
height = height;
}

_bmi = weight / pow(height / 100, 2);
return _bmi.toStringAsFixed(1);
}
}
第三回合
目标:为了能够选择三个按钮之一,所选按钮将具有不同的颜色(如Button2在下面),然后当我单击计算按钮时,我可以打印按钮的标题(即Button2)。
Example of Button2 selected
目前,除打印内容外,其他所有功能均可用。尽管实际上选择了什么按钮,但我只能获取有关Button1的信息(如果使用selected.option,则将得到“Option.one”;如果使用了selected.title,则将得到“Button1”)。
MyButton代码
class MyButton extends ValueNotifier<Option> {
final String _title1;
final String _title2;
final String _title3;

MyButton(
{Option option = Option.one,
String title1 = 'A',
String title2 = 'B',
String title3 = 'C'})
: _title1 = title1,
_title2 = title2,
_title3 = title3,
super(option);

//You can add a get method to retrieve the title based on the option selected with a switch
String get title {
switch (value) {
case Option.one:
return _title1;
case Option.two:
return _title2;
case Option.three:
return _title3;
default:
return _title1; //or a default String, but to be honest this will never be used
}
}

Option get option => value;
set option(Option newOption) => value = newOption;
}
TriButton代码
enum Option {
one,
two,
three,
}

class TriButton extends StatefulWidget {
TriButton(
{this.title1, this.title2, this.title3, this.triWidth, this.myButton});

final String title1;
final String title2;
final String title3;
final Constraints triWidth;
final MyButton myButton;

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

class _TriButtonState extends State<TriButton> {
Option selectedOption;

@override
Widget build(BuildContext context) {
return Center(
child: Container(
constraints: widget.triWidth,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: RectButton(
buttonChild: Text(
widget.title1,
style: TextStyle(color: Colors.white),
),
onPress: () {
setState(() {
selectedOption = Option.one;
});
},
bgColor: selectedOption == Option.one
? kActiveButtonColor
: kInactiveButtonColor,
),
),
Expanded(
child: RectButton(
buttonChild: Text(
widget.title2,
style: TextStyle(color: Colors.white),
),
onPress: () {
setState(() {
selectedOption = Option.two;
});
},
bgColor: selectedOption == Option.two
? kActiveButtonColor
: kInactiveButtonColor,
),
),
Expanded(
child: RectButton(
buttonChild: Text(
widget.title3,
style: TextStyle(color: Colors.white),
),
onPress: () {
setState(() {
selectedOption = Option.three;
});
},
bgColor: selectedOption == Option.three
? kActiveButtonColor
: kInactiveButtonColor,
),
),
],
),
),
);
}
}
输入屏幕
class InputScreen extends StatefulWidget {
static const String id = 'adjustments';

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

class _InputScreenState
extends State<InputScreen> {
final TextEditingController weightController = TextEditingController();
final TextEditingController heightController = TextEditingController();
final TextEditingController creatController = TextEditingController();
final MyUnit heightUnit = MyUnit();
final MyUnit weightUnit = MyUnit(imperial: 'lbs', metric: 'kg');
final MyUnit creatUnit = MyUnit(imperial: 'mg/dL', metric: 'mg/dL');
final MyButton selected = MyButton();

@override
void dispose() {
super.dispose();
weightController.dispose();
heightController.dispose();
creatController.dispose();
heightUnit.dispose();
weightUnit.dispose();
selected.dispose();
}

Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xff142651),
body: Column(
children: <Widget>[
AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
Navigator.pop(context);
}),
],
title: Text('Dose Adjustment'),
backgroundColor: Colors.transparent,
elevation: 0.0,
),
ValueListenableBuilder<Option>(
valueListenable: selectedAbx,
builder: (context, option, _) => TriButton(
title1: 'Button 1',
title2: 'Button 2',
title3: 'Button 3',
),
),
InputRow(
myUnit: heightUnit,
inputParameter: 'height',
textField: heightController,
colour: kOrangePantone,
),
InputRow(
myUnit: weightUnit,
inputParameter: 'weight',
textField: weightController,
colour: kRoyalPurple,
),
InputRow(
myUnit: creatUnit,
inputParameter: 'SCr',
textField: creatController,
colour: kDogwoodRose,
),
RoundedButton(
title: 'Calculate',
onPressed: () {
print(selected.option);
String inputHeight = heightController.text;
String inputWeight = weightController.text;
String inputCreat = creatController.text;

double imperialHeight = double.parse(inputHeight) * 2.54;
double metricHeight = double.parse(inputHeight);
double imperialWeight = double.parse(inputWeight) / 2.2;
double metricWeight = double.parse(inputWeight);

double creat = double.parse(inputCreat);

CalculatorTest calc;
if (heightUnit.unitType == 'cm' && weightUnit.unitType == 'kg') {
calc = CalculatorTest(
height: metricHeight,
weight: metricWeight,
creatinine: creat);
} else if (heightUnit.unitType == 'inches' &&
weightUnit.unitType == 'lbs') {
calc = CalculatorTest(
height: imperialHeight,
weight: imperialWeight,
creatinine: creat);
} else if (heightUnit.unitType == 'cm' &&
weightUnit.unitType == 'lbs') {
calc = CalculatorTest(
height: metricHeight,
weight: imperialWeight,
creatinine: creat);
} else {
heightUnit.unitType == 'inches' && weightUnit.unitType == 'kg';
calc = CalculatorTest(
height: imperialHeight,
weight: metricWeight,
creatinine: creat);
}
;

Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ResultsScreen(
bmiResult: calc.calculate(),
),
),
);
},
),
],
),
);
}
}

最佳答案

在自定义窗口小部件上,为TextField添加参数TextEditingController。

class InputRow extends StatefulWidget {
InputRow({this.inputParameter, this.unit1, this.unit2, this.textField});
final String inputParameter;
final String unit1;
final String unit2;
final TextEditingController textField; //Add this controller and also to the parameters of the constructor

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



class _InputRowState extends State<InputRow> {
String newTaskTitle;
Units selectedUnit;
String unit;

@override
void initState() {
super.initState();
setState(() {
unit = widget.unit1;
});
}

@override
Widget build(BuildContext context) {
return Container(
constraints: BoxConstraints(maxWidth: 375, maxHeight: 50),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: AutoSizeText(
widget.inputParameter,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
),
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.red,
width: 3,
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
bottomLeft: Radius.circular(10),
),
),
child: TextField(
controller: widget.textField, // <-- The Controller
autofocus: true,
textAlign: TextAlign.center,
onChanged: (newText) {
newTaskTitle = newText;
},
),
),
),
Container(
decoration: BoxDecoration(
color: Colors.red,
border: Border.all(
color: Colors.red,
width: 3,
),
borderRadius: BorderRadius.only(
topRight: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
child: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(5),
child: Center(
child: AutoSizeText(
unit,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
)),
),
Container(
constraints: BoxConstraints(maxHeight: 50, maxWidth: 60),
child: FlatButton(
highlightColor: Colors.transparent,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.loop,
size: 25,
),
],
),
onPressed: () {
setState(() {
selectedUnit = selectedUnit == Units.unit2
? Units.unit1
: Units.unit2;
if (selectedUnit == Units.unit1) {
unit = widget.unit1;
} else {
unit = widget.unit2;
}
});
},
)),
],
),
),
],
),
);
}
}
在父窗口小部件(调用自定义窗口小部件的屏幕)上,为每个您想知道的TextField创建TextEditingController,它们具有一个参数TextEditingController.text,该参数为您提供了在控制
class InputScreen extends StatefulWidget {
static const String id = 'adjustments';

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

class AdjustmentInputScreenState extends State<InputScreen> {
final TextEditingController weightController = TextEditingController(); //create one for the height
final TextEditingController heightController = TextEditingController(); //create one for the width


//don't forget to dispose them
@override
void dispose(){
super.dispose();
weightController.dispose();
heightController.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
Navigator.pop(context);
}),
],
title: Text('Dose Adjustment'),
backgroundColor: Colors.transparent,
elevation: 0.0,
),
InputRow(
unit1: 'cm',
unit2: 'inches',
inputParameter: 'height',
textField: heightController, // The textcontroller to check the height
),
InputRow(unit1: 'lbs', unit2: 'kg', inputParameter: 'weight',
textField: weightController, // The textcontroller to check the weight
),
FlatButton(
child: Text('Calculate'),
onPressed: () {
//int.tryparse if you want a number, check for null, empty strings or strings that aren't number
String height = heightController.text;
String weight = weightController.text;
print('Height: $height');
print('Weight: $weight');
//Do your math here
},
),
],
),
);
}
}
使用heightController.text或weightController.text,只要您将TextEditingController附加到要查看的TextField小部件,您就可以在父级的任何地方看到该值
更新
尝试看看TextEditingController是如何工作的,您将看到它扩展了一个ValueNotifier类,该类会在值更改时重建其侦听器,您可以像这样创建自己的侦听器
class MyUnit extends ValueNotifier<Units>{ //You want to check when the enum Units change, so that will be your ValueNotifier
final String _label1;
final String _label2;

MyUnit({Units unit = Units.unit1, String label1 = 'cm', String label2 = 'inches'}) : _label1 = label1, _label2 = label2, super(unit);

String get label => value == Units.unit1 ? _label1 : _label2; //The labels you define, just like unit1 and unit2 in InputRow
Units get unit => value; //the enum value
set unit(Units newUnit) => value = newUnit; //when this change, it will rebuild the listeners
}
现在,就像TextEditingController一样,您只需要创建它们并处理它们
final MyUnit heightUnit = MyUnit();
final MyUnit weightUnit = MyUnit(label1: 'lbs', label2: 'kg');


//don't forget to dispose them
@override
void dispose(){
super.dispose();
weightController.dispose();
heightController.dispose();
heightUnit.dispose();
weightUnit.dispose();
}

...

InputRow(
myUnit: heightUnit,
inputParameter: 'height',
textField: heightController,
),
InputRow(myUnit: weightUnit, inputParameter: 'weight',
textField: weightController,
),
FlatButton(
child: Text('Calculate'),
onPressed: () {
//I change the names of the variables to avoid confusion
String myHeight = heightController.text;
String myWeight = weightController.text;
String labelHeight = heightUnit.label;
String labelWeight = weightUnit.label;
print('Height: $myHeight $labelHeight');
print('Weight: $myWeight $labelWeight');

double weight = double.parse(myWeight); //this could throw an error if myWeight cannot be parsed
if(weightUnit.unit == Units.unit1) weight = weight / 2.2;
print(weight.toStringAsFixed(1));
//Do your math here
},
),
在InputRow中,您可以像TextEditingController一样传递此类,现在您无需再给其他值提供unit1,unit2,selectedUnit,因为该逻辑现在在MyUnit类中
class InputRow extends StatefulWidget {
InputRow({this.inputParameter, this.textField, this.myUnit});
final String inputParameter;
final MyUnit myUnit;
final TextEditingController textField; //Add this controller and also to the parameters of the constructor

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



class _InputRowState extends State<InputRow> {

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

@override
Widget build(BuildContext context) {
return Container(
constraints: BoxConstraints(maxWidth: 375, maxHeight: 50),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
child: Text(
widget.inputParameter,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
),
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: Colors.red,
width: 3,
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
bottomLeft: Radius.circular(10),
),
),
child: TextField(
controller: widget.textField, // <-- The Controller
autofocus: true,
textAlign: TextAlign.center,
),
),
),
Container(
decoration: BoxDecoration(
color: Colors.red,
border: Border.all(
color: Colors.red,
width: 3,
),
borderRadius: BorderRadius.only(
topRight: Radius.circular(10),
bottomRight: Radius.circular(10),
),
),
child: Row(
children: <Widget>[
Container(
padding: EdgeInsets.all(5),
child: Center(
child: ValueListenableBuilder<Units>( //This work as a listener
valueListenable: widget.myUnit, //the object to listen, it needs to extend a ValueNotifier
builder: (context, unit, _) =>
Text(widget.myUnit.label,style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500))
/*
The builder gives me a value unit, that I can use when the ValueListenableBuilder rebuilds,
but that is the Units enum, which you don't want to display, so you ignore it and give widget.myUnit.label to the Text widget, it will rebuild only when Units change, but the label also getter also change with that value, so it's ok
*/
)
),
),
Container(
constraints: BoxConstraints(maxHeight: 50, maxWidth: 60),
child: FlatButton(
highlightColor: Colors.transparent,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.loop,
size: 25,
),
],
),
onPressed: () {
Units unit = widget.myUnit.unit;
widget.myUnit.unit = unit == Units.unit1 ? Units.unit2 : Units.unit1; //this will call the setter in MyUnit and rebuild the listeners
},
)),
],
),
),
],
),
);
}
}
TriButton代码
如您所见,我尝试使用值通知程序,但无法弄清楚如何获得所选按钮的标题。我不知道如何将信息拉到下一个屏幕。
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'rect_button.dart';
import 'package:pocketpk/constants.dart';

enum Option {
one,
two,
three,
}

class TriButton extends StatefulWidget {
TriButton(
{this.title1, this.title2, this.title3, this.triWidth, this.onChanged});

final String title1;
final String title2;
final String title3;
final Constraints triWidth;
ValueChanged<Option> onChanged;

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

class _TriButtonState extends State<TriButton> {
Option selectedOption;

@override
Widget build(BuildContext context) {
return Center(
child: Container(
constraints: widget.triWidth,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: ValueListenableBuilder<Option>(
valueListenable: widget.onChanged,
builder: (context, option, _) => RectButton(
buttonChild: Text(
widget.title1,
style: TextStyle(color: Colors.white),
),
onPress: () {
setState(() {
selectedOption = Option.one;
});
},
bgColor: selectedOption == Option.one
? kActiveButtonColor
: kInactiveButtonColor,
),
),
),
Expanded(
child: ValueListenableBuilder<Option>(
valueListenable: widget.onChanged,
builder: (context, option, _) => RectButton(
buttonChild: Text(
widget.title2,
style: TextStyle(color: Colors.white),
),
onPress: () {
setState(() {
selectedOption = Option.two;
});
},
bgColor: selectedOption == Option.two
? kActiveButtonColor
: kInactiveButtonColor,
),
),
),
Expanded(
child: ValueListenableBuilder<Option>(
valueListenable: widget.onChanged,
builder: (context, option, _) => RectButton(
buttonChild: Text(
widget.title3,
style: TextStyle(color: Colors.white),
),
onPress: () {
setState(() {
selectedOption = Option.three;
});
},
bgColor: selectedOption == Option.three
? kActiveButtonColor
: kInactiveButtonColor,
),
),
),
],
),
),
);
}
}

通知程序
import 'package:flutter/material.dart';
import 'package:pocketpk/widgets/tri_button.dart';

class MyButton extends ValueNotifier<Option> {
final String _title1;
final String _title2;
final String _title3;

MyButton(
{Option option = Option.one,
String title1 = 'A',
String title2 = 'B',
String title3 = 'C'})
: _title1 = title1,
_title2 = title2,
_title3 = title3,
super(option);

//You can add a get method to retrieve the title based on the option selected with a switch
String get title {
switch (value) {
case Option.one:
return _title1;
case Option.two:
return _title2;
case Option.three:
return _title3;
default:
return _title1; //or a default String, but to be honest this will never be used
}
}

Option get option => value;
set option(Option newOption) => value = newOption;
}
更新
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'rect_button.dart';
import 'package:pocketpk/constants.dart';

enum Option {
one,
two,
three,
}

class Parent extends StatelessWidget{
ValueNotifier<Option> myButton = MyButton();

@override
Widget build(BuildContext context){
return ValueListenableBuilder<Option>(
valueListenable: myButton,
builder: (context, button, _) => TriButton(
title1: button.title1, //take the underscores of the names in the MyButton class to make them public
title2: button.title2,
title3: button.title3,
triWidth: BoxConstraints(), //I don't know this value
onChanged: (newOption) => button.option = newOption,
)
);
}
}

class TriButton extends StatefulWidget {
TriButton(
{this.title1, this.title2, this.title3, this.triWidth, this.onChanged});

final String title1;
final String title2;
final String title3;
final Constraints triWidth;
ValueChanged<Option> onChanged;

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

class _TriButtonState extends State<TriButton> {

@override
Widget build(BuildContext context) {
return Center(
child: Container(
constraints: widget.triWidth,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: RectButton(
buttonChild: Text(
widget.title1,
style: TextStyle(color: Colors.white),
),
onPress: () {
widget.onChanged(Option.one);
},
bgColor: selectedOption == Option.one
? kActiveButtonColor
: kInactiveButtonColor,
),
),
Expanded(
child: RectButton(
buttonChild: Text(
widget.title2,
style: TextStyle(color: Colors.white),
),
onPress: () {
widget.onChanged(Option.two);
},
bgColor: selectedOption == Option.two
? kActiveButtonColor
: kInactiveButtonColor,
),
),
Expanded(
child: RectButton(
buttonChild: Text(
widget.title3,
style: TextStyle(color: Colors.white),
),
onPress: () {
widget.onChanged(Option.three);
},
bgColor: selectedOption == Option.three
? kActiveButtonColor
: kInactiveButtonColor,
),
),
],
),
),
);
}
}

关于flutter - 将数据从自定义小部件文本字段传递到计算器 flutter ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62316666/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com