Как получить данные и изменить их значение с помощью showModalBottomSheet от flutter? - PullRequest
0 голосов
/ 05 мая 2020

Я реализовал showModalBottomSheet, который вызывает виджет с отслеживанием состояния. Я хотел бы, чтобы виджет с отслеживанием состояния мог получать данные из вызова showModalBottomSheet и изменять их.

Ниже приведен мой родительский класс, вызывающий функцию showModalBottomSheet:

class _parentClass extends StatelessWidget {
  bool testing = false; //This is the variable that I am trying to change.

  @override
  Widget build(BuildContext context) {

    void _callModalBottomSheet() {
      showModalBottomSheet(
          context: context,
          builder: (BuildContext bc) {
            return Wrap(
              children: <Widget>[
                Container(
                  child: myStatefulWidget(testingValue: testing),
              ),
            ]);
          });

      print("Testing Value: $testing");
    }

    return Column(
      children: <Widget>[
        FlatButton(
                  child: Text("my button"),
                  onPressed: _callModalBottomSheet,
                ),
      ],
    );
  }
}

'myStatefulWidget' на самом деле является еще одним классом, реализованным в совершенно новом файле, поэтому единственный способ получить доступ к переменной 'testing' - через ее конструктор (по крайней мере, единственный способ, который я знаю).

Я пробовал это, но выдает ошибку:

class myStatefulWidget extends StatefulWidget {
  final testingValue;

  myStatefulWidget({
    this.testingValue,
  });

  //testingValue = !testingValue; //This line throws an error!

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

//...

Большое спасибо за вашу помощь!

Ответы [ 2 ]

0 голосов
/ 06 мая 2020

Мне удалось решить эту проблему за 3 шага:

1) создание функции, которая выполняет фактическую модификацию значения в родительском виджете (и отправляет ее в statefulWidget):

class _parentClass extends StatelessWidget {
  bool testing = false; //This is the variable that I am trying to change.
  void changeTesting(bool newValue){
    testing = newValue;
  }

  @override
  Widget build(BuildContext context) {

    void _callModalBottomSheet() {
      showModalBottomSheet(
          context: context,
          builder: (BuildContext bc) {
            return Wrap(
              children: <Widget>[
                Container(
                  child: myStatefulWidget(testingValue: testing, changeTesting: changeTesting),
              ),
            ]);
          });

      print("Testing Value: $testing");
    }

    return Column(
      children: <Widget>[
        FlatButton(
                  child: Text("my button"),
                  onPressed: _callModalBottomSheet,
                ),
      ],
    );
  }
}

2) Получение этой функции в StatefulWidget:

class myStatefulWidget extends StatefulWidget {
  final testingValue;
  final Function(bool) changeTesting;

  myStatefulWidget({
    this.testingValue,
    this.changeTesting,
  });

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

И, наконец, 3) вызов этой функции при нажатии кнопки в состоянии statefulwidget.

class myStatefulWidgetState extends State<myStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return FlatButton(
                    onPressed: (){widget.changeTesting(!widget.testingValue);Navigator.pop(context);},
                    child: Icon(Icons.check, color: Colors.white, size: 30.0,),
                  );
     }
  }

Этот конкретный пост в блоге был очень полезен: https://alligator.io/flutter/widget-communication/

Я также нашел другую методологию, которая лучше подходит для случаев, когда данные необходимо отправить на многие виджеты в дальнейшем. Решение называется унаследованными виджетами. Все эти ссылки были полезны (хотя решение довольно сложное): - Лучший способ передачи данных между виджетами во Flutter - Flutter: как правильно использовать унаследованный виджет? - https://medium.com/flutter-community/simple-ways-to-pass-to-and-share-data-with-widgets-pages-f8988534bd5b - https://medium.com/flutter/managing-flutter-application-state-with-inheritedwidgets-1140452befe1 - https://www.youtube.com/watch?v=pi0X-QWWfIk

0 голосов
/ 06 мая 2020

Вы можете вызвать метод setState в методе showModalBottomSheet, чтобы новые данные могли быть отражены в scree. вам необходимо передать значение в методе navigator.pop.

Следующий код поможет вам лучше понять.

Полная рабочая демонстрация:

class DeleteWidget extends StatefulWidget {
  @override
  _DeleteWidgetState createState() => _DeleteWidgetState();
}

class _DeleteWidgetState extends State<DeleteWidget> {
  bool testing = false; //This is the variable that I am trying to change.

  @override
  Widget build(BuildContext context) {
    void _callModalBottomSheet() {
      showModalBottomSheet(
          context: context,
          builder: (BuildContext bc) {
            return Wrap(children: <Widget>[
              Container(
                child: myStatefulWidget(testingValue: testing),
              ),
            ]);
          }).then((value) {
        setState(() {
          testing = value;
        });
      });

      print("Testing Value: $testing");
    }

    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(testing.toString()),
          FlatButton(
            child: Text("my button"),
            onPressed: _callModalBottomSheet,
          ),
        ],
      ),
    );
  }
}

class myStatefulWidget extends StatefulWidget {
  final bool testingValue;
  myStatefulWidget({this.testingValue});
  @override
  _myStatefulWidgetState createState() => _myStatefulWidgetState();
}

class _myStatefulWidgetState extends State<myStatefulWidget> {
  bool index;
  @override
  void initState() {
    super.initState();
    index = widget.testingValue;
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(index.toString()),
        RaisedButton(
          child: Text("change counter value"),
          onPressed: () {
            setState(() {
              index = !index;
            });
          },
        ),
        RaisedButton(
          child: Text("close sheet"),
          onPressed: () {
            Navigator.pop(context, index);
          },
        )
      ],
    );
  }
}
...