【问题标题】:Flutter - Rebuild parent after calling setState in grandchildrenFlutter - 在孙子中调用 setState 后重建父级
【发布时间】:2019-12-17 00:38:08
【问题描述】:

我有一个带有主页的类和另一个带有对话框的类(当用户单击浮动按钮时出现)。

主页上有一个 TextField,我想在从对话框中的下拉菜单中选择一些内容后(立即)更新它(它距离 TextField 很远,并且在另一个类中)。我怎样才能告诉颤振重建那个(父)类?

它对我不起作用,在应用您所写的更改后,我的下拉菜单中没有任何选项,并且不可点击。

DropdownButton<double>(
   hint: Text("Specify sleep lenght"),
   value: dropdownValue,
   onChanged: onValueChange,
   items: availableLengthHours.map((l) {
     return DropdownMenuItem(
        child: new Center(child: Text(l.toString())),
        value: l,
     );
   }).toList(),
),

【问题讨论】:

  • 如何使用全局变量。我的意思是在你的类中声明一个变量,然后在你的对话框项上选择更新状态。例如;字符串文本=“嗨”;在您的对话框项目上选择 setState({ ClassName.text = "New Text"; });

标签: android flutter dart


【解决方案1】:

Jacek,不确定您尝试了什么,但实现您想要的一种方法是使用您的对话框选择作为Navigator.push 的结果。这是一个简单的例子,

class MyApp extends StatefulWidget {
  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  String text = 'Original text';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
          appBar: AppBar(title: Text('Test'),),
            body: Center(
                        child: Column(
                            mainAxisAlignment: MainAxisAlignment.center,
                            children: [
                          Padding(
                              padding: const EdgeInsets.only(
                                  left: 10.0, right: 10.0),
                              child: Column(children: <Widget>[
                                Text(text, style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.bold)),
                              ]))
                        ])),
          floatingActionButton: Builder( builder: (context) => FloatingActionButton(
            child: Icon(Icons.refresh),
            onPressed: () async {
              update(context);
            },
          )),
        ),
    );
  }

  update(BuildContext context) async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => Dialog()),
    );

    setState(() {
      text= result;
    });
  }
}

class Dialog extends StatelessWidget {
  String dropdownValue = 'Updated item 1';
  @override
  Widget build(BuildContext context) {
    return AlertDialog(
            title: new Text('Test dialog'),
            content: DropdownButton<String>(
              value: dropdownValue,
              icon: Icon(Icons.arrow_downward),
              iconSize: 24,
              elevation: 16,
              style: TextStyle(color: Colors.deepPurple),
              underline: Container(
                height: 2,
                color: Colors.deepPurpleAccent,
              ),
              onChanged: (String newValue) {
                Navigator.pop(context, newValue);
              },
              items: <String>[
                'Updated item 1',
                'Updated item 2',
                'Updated item 3',
                'Updated item 4'
              ].map<DropdownMenuItem<String>>((String value) {
                return DropdownMenuItem<String>(
                  value: value,
                  child: Text(value),
                );
              }).toList(),
            ),
            actions: <Widget>[
              // usually buttons at the bottom of the dialog
              new FlatButton(
                child: new Text('Cancel'),
                onPressed: () {
                  Navigator.pop(context, true);
                },
              )
            ],
          );
  }
}

希望这一切顺利。

【讨论】:

  • 谢谢,但我会接受 Kaplesh 的回答,因为这正是我想要的。 (是的,我没有指定刷新的事情必须同时发生)
【解决方案2】:

这个用例需要两件事

  1. ValueNotifier&lt;String&gt;:仅在选择值时更新您的 Text 小部件。
  2. showDialog&lt;String&gt;:返回字符串值的对话框。

使用ValueNotifier 会很有效,因为您可以定位您的 Text 小部件,并且仅在值更改时重新构建它。这将避免在您的屏幕上不必要地重建一些不使用此值的任意 Widget。

以下是供您参考的工作代码: Run on DartPad

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: AppContent(),
    );
  }
}

class AppContent extends StatelessWidget {
  final ValueNotifier<String> _textValue = ValueNotifier<String>('Default Text');
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Demo',),),
        body: ChildWidget(_textValue),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            showDialog<String>(
                context: context,
                builder: (BuildContext dialogContext) {
                  return Dialog(
                    onValuePicked: (String value) {
                      Navigator.pop(context, value);
                    },
                  );
                }).then((String value) {
              if (value != null && value.isNotEmpty) {
                _textValue.value = value;
              }
            });
          },
        ),
      );
  }
}

class ChildWidget extends StatelessWidget {
  final ValueNotifier<String> textValue;
  ChildWidget(this.textValue);

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder(
      builder: (BuildContext context, value, Widget child) {
        return Text(value,  style: Theme.of(context).textTheme.display2,);
      },
      valueListenable: textValue,
    );
  }
}

class Dialog extends StatelessWidget {
  final ValueChanged<String> onValuePicked;
  static const List<String> items = <String>[
    'item 1',
    'item 2',
    'item 3',
    'item 4'
  ];
  static String dropdownValue = items[0];

  Dialog({Key key, this.onValuePicked}) : super(key: key);

  @override
  Widget build(BuildContext context) => AlertDialog(
        title: new Text('Item picker'),
        content: DropdownButton<String>(
          value: dropdownValue,
          onChanged: onValuePicked,
          items: items.map<DropdownMenuItem<String>>(
            (String value) {
              return DropdownMenuItem<String>(
                value: value,
                child: Text(value),
              );
            },
          ).toList(),
        ),
      );
}

【讨论】:

  • 它对我不起作用,在应用您所写的更改后,我的下拉菜单中没有任何选项,并且不可点击。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
  • 2019-03-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多