flutter - 当按钮位于父级时,如何从子级到父级获得值(value)?

标签 flutter dart callback stepper

我一直在 flutter 地使用Stepper View 。由于按钮位于父窗口小部件中,因此在单击按钮时从子对象向父对象获取值时遇到问题。
这是我的 parent 类和我的 child 类。
父类
这是我的父类,具有带有“下一步”和“后退”按钮的“步进” View 。当我单击“下一步”按钮时,我想从子类到父类获取值(value)。

   class DeliveryTimeline extends StatefulWidget {
      DeliveryTimeline({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    
    class _MyHomePageState extends State<DeliveryTimeline> {
      int _currentStep = 0;
      String shippingtype;
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
            appBar: AppBar(
              backgroundColor: Colors.white,
              centerTitle: true,
              iconTheme: new IconThemeData(color: Colors.black),
              elevation: 0,
              title: Text(
                "Checkout",
                style: TextStyle(color: Colors.black),
              ),
            ),
            body: Stepper(
                type: StepperType.horizontal,
                steps: _mySteps(),
                currentStep: this._currentStep,
                onStepTapped: (step) {
                  setState(() {
                    this._currentStep = step;
                  });
                },
                onStepContinue: () {
                  setState(() {
                    if (this._currentStep == 0) {
                      this._currentStep = this._currentStep + 1;

**//need to get value here on first next click**

                    } else if (this._currentStep == 1) {
                      this._currentStep = this._currentStep + 1;
                    } else {
                      print('Completed, check fields.');
                    }
    
                  });
                },
                onStepCancel: () {
                  setState(() {
                    if (this._currentStep > 0) {
                      this._currentStep = this._currentStep - 1;
                    } else {
                      this._currentStep = 0;
                    }
                  });
                },
                controlsBuilder: (BuildContext context,
                    {VoidCallback onStepContinue,
                    VoidCallback onStepCancel,
                    Function onShippingNextClick}) {
                  return Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: <Widget>[
                      OutlineButton(
                          child: new Text("Back"),
                          onPressed: onStepCancel,
                          shape: new RoundedRectangleBorder(
                              borderRadius: new BorderRadius.circular(4.0))),
                      MaterialButton(
                        child: Text("Next"),
                        color: AppColors.primarycolor,
                        textColor: Colors.white,
                        onPressed: onStepContinue,
                      ),
                    ],
                  );
                }));
      }
    
      List<Step> _mySteps() {
        List<Step> _steps = [
          Step(
            title: Text('Delivery'),
            content: Center(
              child: Container(
                height: MediaQuery.of(context).size.height / 1.5,
                child: Delivery(onShipingTypeClicked: (shippingtype){
                  shippingtype = shippingtype;
                  print("myvalue${shippingtype}");
                },),
              ),
            ),
            isActive: _currentStep >= 0,
          ),
          Step(
            title: Text('Address'),
            content: Address(),
            isActive: _currentStep >= 1,
          ),
          Step(
            title: Text('Payment'),
            content: Payment(),
            isActive: _currentStep >= 2,
          )
        ];
        return _steps;
      }
    
    
    }
child 类
这是我的子类,我有一个Listview,其作用类似于单选按钮。单击按钮时,我希望选定的项目及其对父类的值。
class Delivery extends StatefulWidget {
  final ValueChanged<String> onShipingTypeClicked;

   Delivery({this.onShipingTypeClicked});

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

class _DeliveryState extends State<Delivery> {

  List<RadioModel> sampleData = new List<RadioModel>();




  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    sampleData.add(new RadioModel(false, 'A', 0xffe6194B, "Standard Delivery",
        "Order will be delivered between 3 - 5 business days", 1));
    sampleData.add(new RadioModel(
        true,
        'A',
        0xffe6194B,
        "Next Day Delivery",
        "Place your order before 6pm and your items will be delivered the next day",
        2));
    sampleData.add(new RadioModel(
        false,
        'A',
        0xffe6194B,
        "Nominated Delivery",
        "Pick a particular date from the calendar and order will be delivered on selected date",
        3));


  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: new ListView.builder(
        itemCount: sampleData.length,
        shrinkWrap: true,
        physics: NeverScrollableScrollPhysics(),
        itemBuilder: (BuildContext context, int index) {
          return new InkWell(
              onTap: () {
                setState(() {
                  sampleData.forEach((element) => element.isSelected = false);
                  sampleData[index].isSelected = true;
                  widget.onShipingTypeClicked(sampleData[index].buttonText);
                });
              },
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  TextSmallTitleSize(
                    title: sampleData[index].title,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(bottom: 20.0),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: <Widget>[
                        Flexible(
                          child: TextSmallDimText(sampleData[index].label),
                        ),
                        RadioItem(sampleData[index]),
                      ],
                    ),
                  )
                ],
              ));
        },
      ),
    );
  }
}

class RadioItem extends StatelessWidget {
  final RadioModel _item;

  RadioItem(this._item);

  @override
  Widget build(BuildContext context) {
    return new Container(
      margin: new EdgeInsets.all(15.0),
      child: new Row(
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          new Container(
            height: 25.0,
            width: 25.0,
            alignment: Alignment.center,
            child: Container(
                height: 15.0,
                width: 15.0,
                decoration: new BoxDecoration(
                  color: AppColors.primarycolor,
                  borderRadius:
                      const BorderRadius.all(const Radius.circular(15)),
                )),
            decoration: new BoxDecoration(
              color: Colors.transparent,
              border: new Border.all(
                  width: 3.0,
                  color: _item.isSelected
                      ? AppColors.primarycolor
                      : Colors.transparent),
              borderRadius: const BorderRadius.all(const Radius.circular(25)),
            ),
          ),
          new Container(margin: new EdgeInsets.only(left: 10.0))
        ],
      ),
    );
  }
}

class RadioModel {
  bool isSelected;
  final String buttonText;
  final int colorCode;
  final String title, label;
  final int buttonid;

  RadioModel(this.isSelected, this.buttonText, this.colorCode, this.title,
      this.label, this.buttonid);
}

最佳答案

您可以在下面复制粘贴运行完整代码
您可以使用GlobalKey获取deliveryStateDelivery,并使用deliveryState获取Delivery的属性,此处的属性为RadioModel selected步骤1:使用GlobalKey _key = GlobalKey();

class _MyHomePageState extends State<DeliveryTimeline> {
  ...
  GlobalKey _key = GlobalKey();
步骤2:使用deliveryState获取seleted项目
onStepContinue: () {
          setState(() {
            if (this._currentStep == 0) {
              this._currentStep = this._currentStep + 1;

              final _DeliveryState deliveryState =
                  _key.currentState;
              print("hi ${deliveryState.selected.title} ${deliveryState.selected.label} ");
步骤3:Delivery需要key
child: Delivery(
              key: _key,
              onShipingTypeClicked: (shippingtype) {
 ...
 Delivery({Key key, this.onShipingTypeClicked}) : super(key:key);
步骤4:设定变数selected
RadioModel selected = null;
...
return InkWell(
              onTap: () {
                setState(() {
                  ...
                  selected = sampleData[index];  
工作演示
enter image description here
工作演示的输出
I/flutter ( 6246): hi Standard Delivery Order will be delivered between 3 - 5 business days 
完整的代码
import 'package:flutter/material.dart';

class DeliveryTimeline extends StatefulWidget {
  DeliveryTimeline({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<DeliveryTimeline> {
  int _currentStep = 0;
  String shippingtype;
  GlobalKey _key = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.white,
          centerTitle: true,
          iconTheme: IconThemeData(color: Colors.black),
          elevation: 0,
          title: Text(
            "Checkout",
            style: TextStyle(color: Colors.black),
          ),
        ),
        body: Stepper(
            type: StepperType.horizontal,
            steps: _mySteps(),
            currentStep: this._currentStep,
            onStepTapped: (step) {
              setState(() {
                this._currentStep = step;
              });
            },
            onStepContinue: () {
              setState(() {
                if (this._currentStep == 0) {
                  this._currentStep = this._currentStep + 1;

                  final _DeliveryState deliveryState =
                      _key.currentState;
                  print("hi ${deliveryState.selected.title} ${deliveryState.selected.label} ");

                } else if (this._currentStep == 1) {
                  this._currentStep = this._currentStep + 1;
                } else {
                  print('Completed, check fields.');
                }
              });
            },
            onStepCancel: () {
              setState(() {
                if (this._currentStep > 0) {
                  this._currentStep = this._currentStep - 1;
                } else {
                  this._currentStep = 0;
                }
              });
            },
            controlsBuilder: (BuildContext context,
                {VoidCallback onStepContinue,
                VoidCallback onStepCancel,
                Function onShippingNextClick}) {
              return Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: <Widget>[
                  OutlineButton(
                      child: Text("Back"),
                      onPressed: onStepCancel,
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(4.0))),
                  MaterialButton(
                    child: Text("Next"),
                    color: Colors.blue,
                    textColor: Colors.white,
                    onPressed: onStepContinue,
                  ),
                ],
              );
            }));
  }

  List<Step> _mySteps() {
    List<Step> _steps = [
      Step(
        title: Text('Delivery'),
        content: Center(
          child: Container(
            height: MediaQuery.of(context).size.height / 1.5,
            child: Delivery(
              key: _key,
              onShipingTypeClicked: (shippingtype) {
                shippingtype = shippingtype;
                print("myvalue${shippingtype}");
              },
            ),
          ),
        ),
        isActive: _currentStep >= 0,
      ),
      Step(
        title: Text('Address'),
        content: Text("Address()"),
        isActive: _currentStep >= 1,
      ),
      Step(
        title: Text('Payment'),
        content: Text("Payment()"),
        isActive: _currentStep >= 2,
      )
    ];
    return _steps;
  }
}

class Delivery extends StatefulWidget {
  final ValueChanged<String> onShipingTypeClicked;

  Delivery({Key key, this.onShipingTypeClicked}) : super(key:key);

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

class _DeliveryState extends State<Delivery> {
  List<RadioModel> sampleData = List<RadioModel>();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    sampleData.add(RadioModel(false, 'A', 0xffe6194B, "Standard Delivery",
        "Order will be delivered between 3 - 5 business days", 1));
    sampleData.add(RadioModel(
        true,
        'A',
        0xffe6194B,
        "Next Day Delivery",
        "Place your order before 6pm and your items will be delivered the next day",
        2));
    sampleData.add(RadioModel(
        false,
        'A',
        0xffe6194B,
        "Nominated Delivery",
        "Pick a particular date from the calendar and order will be delivered on selected date",
        3));
  }

  RadioModel selected = null;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView.builder(
        itemCount: sampleData.length,
        shrinkWrap: true,
        physics: NeverScrollableScrollPhysics(),
        itemBuilder: (BuildContext context, int index) {
          return InkWell(
              onTap: () {
                setState(() {
                  sampleData.forEach((element) => element.isSelected = false);
                  sampleData[index].isSelected = true;
                  selected = sampleData[index];
                  widget.onShipingTypeClicked(sampleData[index].buttonText);
                });
              },
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  ListTile(
                    title: Text(sampleData[index].title),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(bottom: 20.0),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceAround,
                      children: <Widget>[
                        Flexible(
                          child: Text(sampleData[index].label),
                        ),
                        RadioItem(sampleData[index]),
                      ],
                    ),
                  )
                ],
              ));
        },
      ),
    );
  }
}

class RadioItem extends StatelessWidget {
  final RadioModel _item;

  RadioItem(this._item);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.all(15.0),
      child: Row(
        mainAxisSize: MainAxisSize.max,
        children: <Widget>[
          Container(
            height: 25.0,
            width: 25.0,
            alignment: Alignment.center,
            child: Container(
                height: 15.0,
                width: 15.0,
                decoration: BoxDecoration(
                  color: Colors.blue,
                  borderRadius:
                      const BorderRadius.all(const Radius.circular(15)),
                )),
            decoration: BoxDecoration(
              color: Colors.transparent,
              border: Border.all(
                  width: 3.0,
                  color: _item.isSelected ? Colors.blue : Colors.transparent),
              borderRadius: const BorderRadius.all(const Radius.circular(25)),
            ),
          ),
          Container(margin: EdgeInsets.only(left: 10.0))
        ],
      ),
    );
  }
}

class RadioModel {
  bool isSelected;
  final String buttonText;
  final int colorCode;
  final String title, label;
  final int buttonid;

  RadioModel(this.isSelected, this.buttonText, this.colorCode, this.title,
      this.label, this.buttonid);
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: DeliveryTimeline(),
    );
  }
}

关于flutter - 当按钮位于父级时,如何从子级到父级获得值(value)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63627538/

相关文章:

Flutter:StreamBuilder 快照——无数据

flutter - 如何解决 flutter for web 中的 web 开发服务器错误?

erlang - Dart:在正在运行的系统中可以即时交换源代码吗?

javascript - JavaScript Promise 中 return 的用法

node.js - 将 Flutter 连接到本地 Nodejs 套接字服务器

firebase - 使用 Firestore : StreamBuilder vs StreamProvider flutter

flutter - 如何在 Dart 中将 RGB 像素图转换为 ui.Image?

flutter - Flutter-在复杂的UI中应该如何进行 Bloc 通信?

callback - Moq中的多个参数回调

javascript - jquery嵌套函数中的全局变量?