flutter,Switch 小部件在 showDialog 中无法正常工作

flutter, Switch widget does not work properly in the showDialog

我找到了 this site 并且我 运行 了代码。 该示例代码运行良好。 此代码在这里。

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    home: MyApp(),
  ));
}

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

class _State extends State<MyApp> {
  bool isSwitched = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Flutter - tutorialkart.com'),
        ),
        body: Center(
          child: Switch(
            value: isSwitched,
            onChanged: (value) {
              setState(() {
                isSwitched = value;
                print(isSwitched);
              });
            },
            activeTrackColor: Colors.lightGreenAccent,
            activeColor: Colors.green,
          ),
        )
    );
  }
}

修复了要放置在 ShowDialog 中的开关小部件。

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    home: MyApp(),
  ));
}

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

class _State extends State<MyApp> {
  bool isSwitched = false;

  @override
  Widget build(BuildContext context) {

    return Scaffold(
        body: Center(
          child: RaisedButton(onPressed: () {
            var ret = showDialog(
              context: context,
              builder: (BuildContext context) {
                return AlertDialog(

                  content: Container(

                    height: MediaQuery.of(context).size.height / 3,
                    child: Center(
                      child: Switch(
                        value: isSwitched,
                        onChanged: (value) {
                          setState(() {
                            isSwitched = value;
                            print(isSwitched);
                          });
                        },
                        activeTrackColor: Colors.lightGreenAccent,
                        activeColor: Colors.green,
                      ),
                    ),
                  ),
                );
              },
            );
          },child: Text("show toggle button"),),
        ),
    );
  }
}

isSwitched 变量未更改。

如果你单独运行开关小部件,它可以正常工作。

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    home: MyApp(),
  ));
}
class MyApp extends StatefulWidget {
  @override
  _State createState() => _State();
}

class _State extends State<MyApp> {

  @override
  Widget build(BuildContext context) {

    return Scaffold(
        body: Center(
          child: RaisedButton(onPressed: () {
            showDialog(
              context: context,
              builder: (BuildContext context) {
                return AlertDialog(

                  content: Container(

                    height: MediaQuery.of(context).size.height / 3,
                    child: Center(
                      child: SwitchWidget(),
                    ),
                  ),
                );
              },
            );
          },child: Text("show toggle button"),),
        ),
    );
  }
}

class SwitchWidget extends StatefulWidget {
  @override
  _SwitchWidgetState createState() => _SwitchWidgetState();
}

class _SwitchWidgetState extends State<SwitchWidget> {
  bool isSwitched = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.transparent,
        body: Center(
          child: Switch(
            value: isSwitched,
            onChanged: (value) {
              setState(() {
                isSwitched = value;
                print(isSwitched);
              });
            },
            activeTrackColor: Colors.lightGreenAccent,
            activeColor: Colors.green,
          ),
        )
    );
  }
}

有没有办法将 Switch Widget 放入 ShowDialog 而无需将其分离到另一个有状态的 widget 中?

您可以复制粘贴 运行 下面的完整代码
您可以在 AlertDialog

content 属性中使用 StatefulBuilder

代码片段

 return AlertDialog(content: StatefulBuilder(
                    builder: (BuildContext context, StateSetter setState) {
                  return Container(

工作演示

完整代码

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    home: MyApp(),
  ));
}

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

class _State extends State<MyApp> {
  bool isSwitched = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          onPressed: () {
            var ret = showDialog(
              context: context,
              builder: (BuildContext context) {
                return AlertDialog(content: StatefulBuilder(
                    builder: (BuildContext context, StateSetter setState) {
                  return Container(
                    height: MediaQuery.of(context).size.height / 3,
                    child: Center(
                      child: Switch(
                        value: isSwitched,
                        onChanged: (value) {
                          setState(() {
                            isSwitched = value;
                            print(isSwitched);
                          });
                        },
                        activeTrackColor: Colors.lightGreenAccent,
                        activeColor: Colors.green,
                      ),
                    ),
                  );
                }));
              },
            );
          },
          child: Text("show toggle button"),
        ),
      ),
    );
  }
}

有很多方法可以实现,但正确的方法是为所有 AlertDialog 使用单独的 StateFul Widget,您可以查看与此主题相关的其他答案 here

另一方面,我可以推荐你在这种你只想操作简单数据的情况下使用ValueNotifier,它使用起来非常简单,试试下一个:

class _State extends State<MyApp> {
  ValueNotifier<bool> _isSwitched = ValueNotifier(false);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: RaisedButton(
          onPressed: () {
            var ret = showDialog(
              context: context,
              builder: (BuildContext context) {
                return AlertDialog(
                  content: Container(
                    height: MediaQuery.of(context).size.height / 3,
                    child: Center(
                      child: ValueListenableBuilder<bool>(
                          valueListenable: _isSwitched,
                          builder: (context, currentState, child) {
                            return Switch(
                              value: currentState,
                              onChanged: (value) {
                                _isSwitched.value = value;
                              },
                              activeTrackColor: Colors.lightGreenAccent,
                              activeColor: Colors.green,
                            );
                          }),
                    ),
                  ),
                );
              },
            );
          },
          child: Text("show toggle button"),
        ),
      ),
    );
  }
}

希望对您有所帮助。