将Flutter Text Field数据传递到父窗口小部件

时间:2020-05-10 09:00:29

标签: flutter widget stateful

如何使用父窗口小部件中的子窗口小部件文本字段数据。

我正在开发计算器类型的 flutter 应用程序。我想

这是主要的计算器课程

class Calculator extends StatefulWidget {
  @override
  _CalculatorState createState() => _CalculatorState();
}

class _CalculatorState extends State<Calculator> {

  double soldPrice=0.00;
 
  void printSoldPrice(){
    print(soldPrice);
  }
  
 

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: BgColor ,
      bottomNavigationBar: Container(
        decoration: BoxDecoration(
          borderRadius:BorderRadius.only(topLeft: Radius.circular(10), topRight:Radius.circular(10) ),
          color:YellowBg,
        ),
        alignment: Alignment.center,
        height: 50,
        
        child: Text('RESET',
        style: TextStyle(
          fontSize: 20,
          fontWeight: FontWeight.w500,
          letterSpacing: 5,

        ),
        ),
      ),

      body: SafeArea(
              child: Column(
          children: <Widget>[
            SizedBox(height:10),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                EcalLogo(logoSize: 30,),  
              ],
            ),
            SizedBox(height:10),
         
            
            Padding(
              padding:EdgeInsets.symmetric(horizontal:10.0),
              child:FractionallySizedBox(
                widthFactor: 0.9,
                child: Container(
                height:1.0,
                width:130.0,
                color:Colors.white,),
              ),),

            SizedBox(height: 10,),

            Expanded(
              child:ListView(
                children: <Widget>[

                  TextFieldContainer1(
                    title: 'SOLD PRICE',
                    tagLine: "SALE PRICE WITOHUT SHIPPING",
                    icon: Icons.check_circle,
                    
                
                  ),
        
                ],
            ))


          ],
        ),
      )
      
    );
  }
}



这是子TextFieldContainer1类

class TextFieldContainer1 extends StatefulWidget {
  final String title;
  final String tagLine;
  final IconData icon;
  
  
  
  TextFieldContainer1({this.title,this.tagLine,this.icon});


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

class _TextFieldContainer1State extends State<TextFieldContainer1> {

  final controller1 = TextEditingController();


  

  @override
  Widget build(BuildContext context) {
    return FractionallySizedBox(
      widthFactor: 0.95,
        child: Container(
         
          padding: EdgeInsets.symmetric(horizontal:20, vertical:5),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.all(Radius.circular(10)),
            color: tileBackground,
          ),                      
          height: 57,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children:<Widget>[
              Container(
                child:Column(
                  
                  children:<Widget>[
                    Row(
                      
                      children:<Widget>[
                        Icon(widget.icon,
                        color: Colors.white,
                        size:27.5
                        ),
                        SizedBox(width:5),
                        Text(widget.title,
                        style: TextStyle(
                          
                          fontSize: 20,
                          color:Colors.white,
                          fontWeight: FontWeight.w500
                        ),
                        )
                      ]          
                    ),
                    Text(widget.tagLine,
                    style: TextStyle(
                      color:Color.fromRGBO(255, 255, 255, 0.5),
                      fontSize: 12
                    ),
                    )
                  ]
                )
              ),
              Container(
                padding: EdgeInsets.symmetric(horizontal: 15,vertical: 5),
                decoration: BoxDecoration(
                  color: Color.fromRGBO(252, 205, 0, 0.2),
                  borderRadius: BorderRadius.all(Radius.circular(10)
                  )
                ),
                height: 40,
                width: 92,
                child: TextField(
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 20
                  ),
                  autofocus: false,
                  decoration:InputDecoration( 
                    focusColor: YellowBg,
                    fillColor: YellowBg,
                    hoverColor: YellowBg,
                    enabledBorder: UnderlineInputBorder(
                      borderSide: BorderSide(color: YellowBg),
                    ),
                    focusedBorder: UnderlineInputBorder(
                      borderSide: BorderSide(color: YellowBg),)
                  ) ,
                  keyboardType: TextInputType.number,
                  controller: controller1,
                  
                 
                ),
              )
            ],
          ),

      ),
    );
  }
}



我想使用TextFieldContainer1类中的 controller1 数据(文本字段中的数据)来更新计算器类中的 soldPrice 变量,并在触发textField onChanged时仅打印该变量。 该怎么做?

3 个答案:

答案 0 :(得分:1)

完整的工作代码:

添加

final Function(String) onChange;

到 TextFieldContainer1

添加

onChanged: widget.onChange,

到 文本域 (并删除Controller)

添加

onChange: (val) => setState(() {
                          soldPrice = double.parse(val);
                          print(val);
                        })

在计算器中调用TextFieldContainer1。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(child: Calculator()),
      ),
    );
  }
}

Color BgColor = Colors.white;
Color YellowBg = Colors.yellow;
Color tileBackground = Colors.black;

class Calculator extends StatefulWidget {
  @override
  _CalculatorState createState() => _CalculatorState();
}

class _CalculatorState extends State<Calculator> {

  double soldPrice=0.00;

  void printSoldPrice(){
    print(soldPrice);
  }



  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: BgColor ,
      bottomNavigationBar: Container(
        decoration: BoxDecoration(
          borderRadius:BorderRadius.only(topLeft: Radius.circular(10), topRight:Radius.circular(10) ),
          color:YellowBg,
        ),
        alignment: Alignment.center,
        height: 50,

        child: Text('RESET',
        style: TextStyle(
          fontSize: 20,
          fontWeight: FontWeight.w500,
          letterSpacing: 5,

        ),
        ),
      ),

      body: SafeArea(
              child: Column(
          children: <Widget>[
            SizedBox(height:10),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                FlutterLogo(size: 30,),  
              ],
            ),
            SizedBox(height:10),


            Padding(
              padding:EdgeInsets.symmetric(horizontal:10.0),
              child:FractionallySizedBox(
                widthFactor: 0.9,
                child: Container(
                height:1.0,
                width:130.0,
                color:Colors.white,),
              ),),

            SizedBox(height: 10,),

            Expanded(
              child:ListView(
                children: <Widget>[

                  TextFieldContainer1(
                    title: 'SOLD PRICE',
                    tagLine: "SALE PRICE WITOHUT SHIPPING",
                    icon: Icons.check_circle,

                    onChange: (val) => setState(() {
                      soldPrice = double.parse(val);
                      print(val);
                    })
                  ),

                ],
            )),
            Text("$soldPrice")

          ],
        ),
      )

    );
  }
}

class TextFieldContainer1 extends StatefulWidget {
  final String title;
  final String tagLine;
  final IconData icon;

  final Function(String) onChange;

  TextFieldContainer1({this.title,this.tagLine,this.icon, this.onChange});


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

class _TextFieldContainer1State extends State<TextFieldContainer1> {

  @override
  Widget build(BuildContext context) {



    return FractionallySizedBox(
      widthFactor: 0.95,
        child: Container(

          padding: EdgeInsets.symmetric(horizontal:20, vertical:5),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.all(Radius.circular(10)),
            color: tileBackground,
          ),                      
          height: 57,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children:<Widget>[
              Container(
                child:Column(

                  children:<Widget>[
                    Row(

                      children:<Widget>[
                        Icon(widget.icon,
                        color: Colors.white,
                        size:27.5
                        ),
                        SizedBox(width:5),
                        Text(widget.title,
                        style: TextStyle(

                          fontSize: 20,
                          color:Colors.white,
                          fontWeight: FontWeight.w500
                        ),
                        )
                      ]          
                    ),
                    Text(widget.tagLine,
                    style: TextStyle(
                      color:Color.fromRGBO(255, 255, 255, 0.5),
                      fontSize: 12
                    ),
                    )
                  ]
                )
              ),
              Container(
                padding: EdgeInsets.symmetric(horizontal: 15,vertical: 5),
                decoration: BoxDecoration(
                  color: Color.fromRGBO(252, 205, 0, 0.2),
                  borderRadius: BorderRadius.all(Radius.circular(10)
                  )
                ),
                height: 40,
                width: 92,
                child: TextField(
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 20
                  ),
                  autofocus: false,
                  decoration:InputDecoration( 
                    focusColor: YellowBg,
                    fillColor: YellowBg,
                    hoverColor: YellowBg,
                    enabledBorder: UnderlineInputBorder(
                      borderSide: BorderSide(color: YellowBg),
                    ),
                    focusedBorder: UnderlineInputBorder(
                      borderSide: BorderSide(color: YellowBg),)
                  ) ,
                  keyboardType: TextInputType.number,
                  onChanged: widget.onChange,
                ),
              )
            ],
          ),

      ),
    );
  }
}

答案 1 :(得分:0)

使文本字段类构造函数接受一个函数,然后在onChange中使用该函数,如下所示:

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

class _TextFieldContainer1State extends State<TextFieldContainer1> {

  final controller1 = TextEditingController();
  final Function onChange;



  @override
  Widget build(BuildContext context) {
    return FractionallySizedBox(
      widthFactor: 0.95,
        child: Container(

          padding: EdgeInsets.symmetric(horizontal:20, vertical:5),
          decoration: BoxDecoration(
            borderRadius: BorderRadius.all(Radius.circular(10)),
            color: tileBackground,
          ),                      
          height: 57,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children:<Widget>[
              Container(
                child:Column(

                  children:<Widget>[
                    Row(

                      children:<Widget>[
                        Icon(widget.icon,
                        color: Colors.white,
                        size:27.5
                        ),
                        SizedBox(width:5),
                        Text(widget.title,
                        style: TextStyle(

                          fontSize: 20,
                          color:Colors.white,
                          fontWeight: FontWeight.w500
                        ),
                        )
                      ]          
                    ),
                    Text(widget.tagLine,
                    style: TextStyle(
                      color:Color.fromRGBO(255, 255, 255, 0.5),
                      fontSize: 12
                    ),
                    )
                  ]
                )
              ),
              Container(
                padding: EdgeInsets.symmetric(horizontal: 15,vertical: 5),
                decoration: BoxDecoration(
                  color: Color.fromRGBO(252, 205, 0, 0.2),
                  borderRadius: BorderRadius.all(Radius.circular(10)
                  )
                ),
                height: 40,
                width: 92,
                child: TextField(
                  textAlign: TextAlign.center,
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 20
                  ),
                  onChange: widget.onChange,
                  autofocus: false,
                  decoration:InputDecoration( 
                    focusColor: YellowBg,
                    fillColor: YellowBg,
                    hoverColor: YellowBg,
                    enabledBorder: UnderlineInputBorder(
                      borderSide: BorderSide(color: YellowBg),
                    ),
                    focusedBorder: UnderlineInputBorder(
                      borderSide: BorderSide(color: YellowBg),)
                  ) ,
                  keyboardType: TextInputType.number,
                  controller: controller1,


                ),
              )
            ],
          ),

      ),
    );
  }
}

现在在计算器类中使用它时,您将像这样使用它:

TextFieldContainer1(
                    title: 'SOLD PRICE',
                    tagLine: "SALE PRICE WITOHUT SHIPPING",
                    icon: Icons.check_circle,
                    onChanga: (value) => print(value);
// now you have access to your text field value inside your calculator class
                  ),

您可能还想将文本字段类设为Stateless,因为您没有在任何地方使用setState

答案 2 :(得分:0)

为textField创建自定义类非常简单。以下是实现此目的的两个步骤。第一步是为文本字段创建有状态窗口小部件。

 RCTextField({
@required this.hintText,
@required this.labelText,
@required this.prefixIcon,
@required this.suffixIcon,
@required this.kType,
@required this.kAction,
@required this.validatorFunction,
@required this.onChange,
});

final String hintText;
final String labelText;
final String prefixIcon;
final String suffixIcon;
final TextInputType kType;
final TextInputAction kAction;
final Function validatorFunction;
final Function(String) onChange;

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

class _RCTextFieldState extends State<RCTextField> {
FocusNode myFocusNode;

get validatorFunction => null;
get textFieldValue => null;
get onChange => null;
@override
void initState() {
  super.initState();
  myFocusNode = FocusNode();
  myFocusNode.addListener(_onOnFocusNodeEvent);
}

_onOnFocusNodeEvent() {
  setState(() {
    // Re-renders
  });
}

@override
void dispose() {
  // Clean up the focus node when the Form is disposed.
  myFocusNode.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  return Container(
    // margin: EdgeInsets.fromLTRB(20, 20, 20, 0),
    child: TextFormField(
    onEditingComplete: () => FocusScope.of(context).nextFocus(),
    textInputAction: widget.kAction,
    cursorColor: Colors.black,
    style: new TextStyle(color: _getInputTextColor()),
    focusNode: myFocusNode,
    validator: validatorFunction,
    decoration: InputDecoration(
      // focusColor: Colors.red,
      // fillColor: Colors.blueGrey,
      enabledBorder: UnderlineInputBorder(
        borderSide: BorderSide(color: kInactiveTextFieldColour),
      ),
      focusedBorder: UnderlineInputBorder(
        borderSide: BorderSide(color: kActiveTextFieldColour),
      ),
      border: UnderlineInputBorder(),
      filled: false,
      prefixIcon: Padding(
        padding: EdgeInsets.all(14.0),
        child: SvgPicture.asset(
          'images/' + widget.prefixIcon + '.svg',
          semanticsLabel: 'Acme Logo',
          color: myFocusNode.hasFocus
              ? kActiveTextFieldColour
              : kInactiveTextFieldColour,
        ),
      ),
      hintText: widget.hintText,
      labelText: widget.labelText,
      labelStyle: TextStyle(
          color: myFocusNode.hasFocus
              ? kActiveTextFieldColour
              : kInactiveTextFieldColour),
    ),
    keyboardType: widget.kType,
    onChanged: widget.onChange,
  ),
);
}

Color _getInputTextColor() {
return myFocusNode.hasFocus ? Colors.black : Colors.black;
}
}

下面是使用此类的最后一步。

RCTextField(
            hintText: 'Enter your text',
            labelText: 'Text',
            prefixIcon: 'plus',
            suffixIcon: null,
            kType: TextInputType.visiblePassword,
            kAction: TextInputAction.done,
            onChange: (val) => setState(() {
              print(val);
            }),
          ),

如果您遇到任何麻烦,请告诉我。