Material 组件库中提供了Material风格的 单选开关Switch 和 复选框Checkbox ,虽然它们都是继承自StatefulWidget,但它们本身不会保存当前选中状态,选中状态都是由父组件来管理的。当Switch或Checkbox被点击时,会触发它们的 onChanged 回调

我们可以在此回调中处理选中状态改变逻辑。下面看一个简单的例子:

  1. import 'package:flutter/material.dart';
  2. void main() => runApp(new MyApp());
  3. class MyApp extends StatelessWidget {
  4. @override
  5. Widget build(BuildContext context) {
  6. return new MaterialApp(
  7. title: '单选开关和复选框',
  8. theme: new ThemeData(
  9. primarySwatch: Colors.blue,
  10. ),
  11. home: new MyHomePage(title: '单选开关和复选框'),
  12. );
  13. }
  14. }
  15. class MyHomePage extends StatefulWidget {
  16. MyHomePage({Key key, this.title}) : super(key: key);
  17. final String title;
  18. @override
  19. _MyHomePageState createState() => new _MyHomePageState();
  20. }
  21. class _MyHomePageState extends State<MyHomePage> {
  22. @override
  23. Widget build(BuildContext context) {
  24. String icons = "\uE914\uE000\uE90D";
  25. return new Scaffold(
  26. appBar: new AppBar(
  27. title: new Text(widget.title),
  28. ),
  29. body: SwitchAndCheckBoxTestRoute());
  30. }
  31. }
  32. class SwitchAndCheckBoxTestRoute extends StatefulWidget {
  33. @override
  34. _SwitchAndCheckBoxTestRouteState createState() =>
  35. new _SwitchAndCheckBoxTestRouteState();
  36. }
  37. class _SwitchAndCheckBoxTestRouteState
  38. extends State<SwitchAndCheckBoxTestRoute> {
  39. bool _switchSelected = true; //维护单选开关状态
  40. bool _checkboxSelected = true; //维护复选框状态
  41. @override
  42. Widget build(BuildContext context) {
  43. return Column(
  44. children: <Widget>[
  45. Switch(
  46. value: _switchSelected, //当前状态
  47. onChanged: (value) {
  48. //重新构建页面
  49. setState(() {
  50. _switchSelected = value;
  51. });
  52. },
  53. ),
  54. Checkbox(
  55. value: _checkboxSelected,
  56. activeColor: Colors.red, //选中时的颜色
  57. onChanged: (value) {
  58. setState(() {
  59. _checkboxSelected = value;
  60. });
  61. },
  62. )
  63. ],
  64. );
  65. }
  66. }

上面代码中,由于需要维护Switch和Checkbox的选中状态,所以SwitchAndCheckBoxTestRoute继承自StatefulWidget 。在其build方法中分别构建了一个Switch和Checkbox,初始状态都为选中状态,当用户点击时,会将状态置反,然后回调用setState()通知Flutter framework重新构建UI。
单选开关和复选框 - 图1

属性及外观

Switch和Checkbox属性比较简单,读者可以查看API文档,

  • 它们都有一个activeColor属性,用于设置激活态的颜色。
  • 至于大小,到目前为止,Checkbox的大小是固定的,无法自定义,而Switch只能定义宽度,高度也是固定的。
  • 值得一提的是Checkbox有一个属性tristate ,表示是否为三态,其默认值为false ,这时Checkbox有两种状态即“选中”和“不选中”,对应的value值为true和false 。如果tristate值为true时,value的值会增加一个状态null,读者可以自行了解

Switch参数属性

  1. (new) Switch Switch({Key key,
  2. bool value,
  3. void Function(bool) onChanged,
  4. Color activeColor,
  5. Color activeTrackColor,
  6. Color inactiveThumbColor,
  7. Color inactiveTrackColor,
  8. ImageProvider<dynamic> activeThumbImage,
  9. ImageProvider<dynamic> inactiveThumbImage,
  10. MaterialTapTargetSize materialTapTargetSize,
  11. DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  12. Color focusColor,
  13. Color hoverColor,
  14. FocusNode focusNode,
  15. bool autofocus = false})

Checkbox参数属性

  1. (new) Checkbox Checkbox({Key key,
  2. bool value,
  3. bool tristate = false,
  4. void Function(bool) onChanged,
  5. Color activeColor,
  6. Color checkColor,
  7. Color focusColor,
  8. Color hoverColor,
  9. MaterialTapTargetSize materialTapTargetSize,
  10. FocusNode focusNode,
  11. bool autofocus = false})

Radio参数属性

  1. (new) Radio<int> Radio({Key key},
  2. {int value},
  3. {int groupValue},
  4. {void Function(int) onChanged},
  5. {Color activeColor},
  6. {Color focusColor},
  7. {Color hoverColor},
  8. {MaterialTapTargetSize materialTapTargetSize},
  9. {FocusNode focusNode},
  10. {bool autofocus})

总结

通过Switch和Checkbox我们可以看到,虽然它们本身是与状态(是否选中)关联的,但它们却不是自己来维护状态,而是需要父组件来管理状态,然后当用户点击时,再通过事件通知给父组件,这样是合理的,因为Switch和Checkbox是否选中本就和用户数据关联,而这些用户数据也不可能是它们的私有状态。我们在自定义组件时也应该思考一下哪种状态的管理方式最为合理。