如何将数据从一个小部件传递到其同级小部件?

时间:2019-10-16 16:56:21

标签: flutter dart

我有一个Column部件,其中包含一个自定义部件(ViewCard)和一个RaisedButton。 ViewCard内部有一些数据,用户可以与之交互和更改。现在,我希望RaisedButton将这些更改或详细信息提交给Firestore。我现在面临的问题是我无法从外部访问自定义窗口小部件的数据。

Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: <Widget>[
          SizedBox(height: 20,),

          ViewCard(args.combo,_changeprice),

          SizedBox(height: 20,),

          Container(
            padding: EdgeInsets.only(top: 15),
            height: 75,
            decoration: BoxDecoration(
              color: Colors.yellow,
              borderRadius: BorderRadius.circular(20)
            ),
            child: Card(
              elevation: 0,
              color: Colors.transparent,
              child: Row(
                children: <Widget>[
                Text("Cart price : $price"),
                SizedBox(width: 75,),
                Container(
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(25),
                    color: Colors.yellow
                  ),
                  child: RaisedButton(
                    onPressed: (){},     
                    child: Text("Host this order"),
                  ),
                ),
              ],)
            ),
          )
        ],
      ),

我需要以某种方式将CardView内部的3个变量传递给当前类,以便可以在RaisedButton中使用它们。

编辑:args.combo的类型为组合

class Combo {
  List<Items> items;
  Combo({this.items});
}
class Items {
  String item;
  String price;
}

这是CardView的代码。此类为args.combo创建了一张卡片

class ViewCard extends StatefulWidget {
  ViewCard(this.combo, this.changePrice);
  final Combo combo;
  final IntCallback changePrice;

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

class _ViewCardState extends State<ViewCard> {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: (50 * widget.combo.items.length + 125).toDouble(),
      padding: EdgeInsets.only(left: 20),
      decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(40), color: Colors.yellow),
      child: Card(
          elevation: 0,
          color: Colors.transparent,
          child: Column(children: <Widget>[
            ListView.builder(
              shrinkWrap: true,
              itemCount: widget.combo.items.length,
              physics: NeverScrollableScrollPhysics(),
              itemBuilder: (context, index) {
                return Column(
                  children: <Widget>[
                    SizedBox(
                      height: 25,
                    ),
                    OneItem(widget.combo, index, widget.changePrice),

                  ],
                );
              },
            ),
          ])),
    );
  }
}

OneItem是另一个类,它通过组合进行迭代以查找其中的项目数。每个项目与CheckBox一起打印在一行中。用户选中了一些复选框,这就是我需要传递给最高级课程的数据。

class OneItem extends StatefulWidget {
  OneItem(this.combo, this.index, this.changePrice);
  final Combo combo;
  final int index;
  final Function changePrice;
  double priceval;

  @override
  State<StatefulWidget> createState() => OneItemState();
}

class OneItemState extends State<OneItem> {
  List<bool> Vals = new List();

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

    int count = widget.combo.items.length;


    Vals = List<bool>.generate(count, (_) => false);
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Align(
          child: Text(widget.combo.items[widget.index].item),
          alignment: Alignment(-1, 0),
        ),
        Align(
            child: Text(widget.combo.items[widget.index].price),
            alignment: Alignment(0.1, 0)),
        Align(
            child: Checkbox(
              value: Vals[widget.index],
              onChanged: (bool value) {
                setState(() {
                  Vals[widget.index] = value;
                  if(value == true){ widget.priceval = double.parse(widget.combo.items[widget.index].price); }
                  else{double val = double.parse(widget.combo.items[widget.index].price); 
                         widget.priceval = -1*val;}
                  widget.changePrice(widget.priceval);
                  print('${widget.priceval}');
                });
              },
            ),
            alignment: Alignment(0.6, 0)),
      ],
    );
  }
}

2 个答案:

答案 0 :(得分:1)

我将在Items类中添加一个变量“复选框” ...

class Items {
  String item;
  String price;
  bool checkbox;
}

...,然后在复选框的onChanged回调中修改每个项目的复选框变量。

Checkbox(
  onChanged: (bool newValue) {
    // set checkbox variable of current item depending on state of UI widget
    ...
  },
)

您的MainWidget可能保持不变,因为您已经向ViewCard提供了Combo对象。

class MyColumnWidget extends StatelessWidget {
  TextEditingController myTextController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: <Widget>[
         SizedBox(height: 20,),
         ViewCard(args.combo,_changeprice),
         RaisedButton(
            onPressed: (){
               // here we have state of checkboxes inside Items objects
               saveToFirestore(args.combo); 
            },        
         ),
      ]
   )
  }
}
  

这是我脑海中写的伪代码。因此它可能无法编译   直接进行操作,但这应该可以指引您正确的方向。

另一种方法是使用诸如提供程序(https://pub.dev/packages/provider)之类的StateManagement库。从长远来看,这可能是更好的方法。

答案 1 :(得分:0)

我认为provider会很好。尽管这不是唯一的选择,但它是Flutter团队推荐的状态管理解决方案。

从本质上讲,问题在于存储在vals数组中的数据位于OneItem小部件内部,该部件深深嵌套在小部件树中,并且您想在小部件树的另一部分中使用该信息。解决方案是在将要使用数据的分支的根处(在本例中为ViewCard上方)实例化数据,然后使用提供程序小部件将复选框值列表“提供”给OneItem小部件和按钮。正在使用Provider.of <data-type-you-are-providing>(上下文)提交数据。