[Flutter]flutter基础之组件基础(十五)

一、showDatePicker Function

showDatePicker 方法显示一个包含日期选择器的对话框 。当用户关闭对话框时,返回的 Future 解析为用户选择的日期。如果用户取消对话框,则返回 null

可以传入一个可选的 selectableDayPredicate 函数来定制天数,以启用选择。如果提供了,那么只有 selectableDayPredicate 返回 true 的天数才是可选择的。可选的 initialDatePickerMode 参数可用于最初在年或月+日选择器模式中显示日期选择器。它默认为月+日,并且不能为空。

可选的语言环境参数可用于设置日期选择器的语言环境。 它默认为 Localizations 提供的环境语言环境。

可选的 textDirection 参数可用于设置日期选择器的文本方向(RTL或LTR)。 它默认为 Directionality 提供的环境文本方向。 如果 localetextDirection 都不为 null ,则 textDirection 会覆盖为语言环境选择的方向。

contextuseRootNavigator 参数传递给 showDialoguseRootNavigator 参数用于确定是否将对话框推到距给定上下文最远或最接近给定上下文的 Navigator 。 默认情况下,useRootNavigatortrue ,并且由此方法创建的对话框路由被推送到根导航器。如果应用程序具有多个 Navigator对象,则可能有必要调用 Navigator.of(context, rootNavigator:true).pop(result)关闭对话框,而不仅仅是 Navigator.pop(context, result)

builder 参数可用于包装对话框窗口小部件以添加继承的窗口小部件,例如 Theme

方法定义如下:

1
Future<DateTime> showDatePicker({
2
  //BuildContext类型必传参数,上下文
3
  @required BuildContext context,
4
  //DateTime类型必传参数,初始化选中的时间日期
5
  @required DateTime initialDate,
6
  //DateTime类型必传参数,可呈现的开始日期
7
  @required DateTime firstDate,
8
  //DateTime类型必传参数,可呈现的结束日期
9
  @required DateTime lastDate,
10
  //SelectableDayPredicate类型可选命名参数,用于设置可选择的时间区域,是一个函数
11
  SelectableDayPredicate selectableDayPredicate,
12
  //DatePickerMode类型可选命名参数,日期对话框的初始显示模式
13
  DatePickerMode initialDatePickerMode = DatePickerMode.day,
14
  //Locale类型可选命名参数,本地化设置
15
  Locale locale,
16
  //TextDirection类型可选命名参数,文本的显示方向
17
  TextDirection textDirection,
18
  //TransitionBuilder类型可选命名参数,构建子Widget的构建器
19
  TransitionBuilder builder,
20
  //bool类型可选命名参数,参数用于确定是否将对话框推到距给定上下文最远或最接近给定上下文的Navigator
21
  bool useRootNavigator = true,
22
})

DateTime 是用来设置日期时间的类。创建对象时,DateTime 对象将锚定在当前计算机的 UTC 时区或本地计算机的本地时区中。创建后,DateTime 对象的值和时区都不能更改。您可以使用属性来获取 DateTime 对象的各个单位。有以下构造方法:

1
//构造在本地时区中指定的DateTime实例
2
DateTime(
3
  //int类型必传参数,年
4
  int year,[
5
  //int类型可选位置参数,月
6
  int month = 1,
7
  //int类型可选位置参数,日
8
  int day = 1,
9
  //int类型可选位置参数,小时
10
  int hour = 0,
11
  //int类型可选位置参数,分钟
12
  int minute = 0,  
13
  //int类型可选位置参数,秒数
14
  int second = 0,
15
  //int类型可选位置参数,毫秒
16
  int millisecond = 0,
17
  //int类型可选位置参数,微妙
18
  int microsecond = 0
19
])
20
21
//构造在UTC时区中指定的DateTime实例
22
DateTime.utc(
23
  //参数与DateTime相同,此处省略
24
])  
25
  
26
//使用本地时区中的当前日期和时间构造一个DateTime实例  
27
DateTime.now()  
28
  
29
//使用给定的毫秒构造一个新的DateTime实例
30
DateTime.fromMillisecondsSinceEpoch(
31
  //int类型必传参数,自1970-01-01T00:00:00Z (UTC)起的毫秒数
32
  int millisecondsSinceEpoch,{
33
  //bool类型可选命名参数,是否为UTC时间
34
  bool isUtc = false
35
})  
36
  
37
//使用给定的微秒构造一个新的DateTime实例
38
DateTime.fromMicrosecondsSinceEpoch(
39
  //int类型必传参数,自1970-01-01T00:00:00Z(UTC)起的微秒数
40
  int microsecondsSinceEpoch,{
41
  //bool类型可选命名参数,是否为UTC时间
42
  bool isUtc = false
43
});

具体可查看官方说明:https://api.flutter.dev/flutter/dart-core/DateTime-class.html

SelectableDayPredicate 是一个返回值为 bool 类型的函数,定义为 bool Function(DateTime day)

DatePickerMode 用于设置日期选择器对话框的初始显示模式。日期选择器UI模式,用于通过调用showDatePicker在显示的对话框中最初显示可用年份列表或月历。是一个枚举类型值,如下:

1
enum DatePickerMode {
2
  //显示用于选择月份和日期的日期选择器用户界面
3
  day,
4
  //显示用于选择年份的日期选择器用户界面
5
  year,
6
}

showDatePicker 使用如下:

1
class _MyHomePageState extends State<MyHomePage> {
2
3
  String _selectResult = "time";
4
5
  callDatePicker() async {
6
    DateTime resultDate = await selectedDate();
7
    setState(() {
8
      _selectResult = resultDate.toString();
9
    });
10
  }
11
12
  Future<DateTime> selectedDate() {
13
    return showDatePicker(
14
      context: context,
15
      initialDate: DateTime.now(),
16
      firstDate: DateTime(1997, 1, 1),
17
      lastDate: DateTime(2100, 1, 1),
18
      selectableDayPredicate: (DateTime dateTime) {
19
        if(dateTime.compareTo(DateTime(2020, 4, 3)) < 0) {
20
          return true;
21
        }
22
        return false;
23
      },
24
      initialDatePickerMode: DatePickerMode.day,
25
      builder: (BuildContext context, Widget child) {
26
        return Theme(
27
          data: ThemeData.dark(),
28
          child: child,
29
        );
30
      },
31
    );
32
  }
33
34
  @override
35
  Widget build(BuildContext context) {
36
    return Scaffold(
37
      appBar: AppBar(
38
        title: Text("HomePage"),
39
      ),
40
      body: Container(
41
          child: Column(
42
            children: <Widget>[
43
              RaisedButton(
44
                child: Text("显示Dialog"),
45
                onPressed: callDatePicker,
46
              ),
47
              Text("$_selectResult"),
48
            ],
49
          ),
50
      ),
51
    );
52
  }
53
}

效果如下:

截屏2020-04-01下午8

二、showTimePicker Function

showTimePicker 方法显示一个包含时间选择器的对话框。返回的 Future 解析为用户关闭对话框时用户选择的时间。如果用户取消对话框,则返回 null

builder 参数可用于包装对话框窗口小部件以添加继承的窗口小部件,例如 Localizations.overrideDirectivityMediaQuery

方法定义如下:

1
Future<TimeOfDay> showTimePicker({
2
  //BuildContext类型必传参数,上下文
3
  @required BuildContext context,
4
  //TimeOfDay类型必传参数,初始化选择的时间
5
  @required TimeOfDay initialTime,
6
  //TransitionBuilder类型可选命名参数,用于包装对话框窗口小部件以添加继承的窗口小部件
7
  TransitionBuilder builder,
8
  //bool类型可选命名参数,参数用于确定是否将对话框推到距给定上下文最远或最接近给定上下文的Navigator
9
  bool useRootNavigator = true,
10
})

TimeOfDay 是一个表示一天中时间值的类。时间以小时和分钟对表示。 创建后,两个值都无法更改。可以使用同时需要小时和分钟的构造函数或使用 DateTime 对象来创建 TimeOfDay 。 与 24 小时制一样,将小时指定在 0 到 23 之间。构造方法有如下:

1
//创建一天中的时间
2
TimeOfDay({
3
  //int类型必传参数,小时,取值范围0到23
4
  @required this.hour, 
5
  //int类型必传参数,分钟
6
  @required this.minute 
7
})
8
9
//根据给定时间创建一天中的时间
10
TimeOfDay.fromDateTime(
11
  //DateTime类型必传参数,用来设置日期时间
12
  DateTime time
13
)  
14
  
15
//根据当前时间创建一天中的时间  
16
TimeOfDay.now()

showTimePicker 使用方法如下:

1
class _MyHomePageState extends State<MyHomePage> {
2
  String _selectResult;
3
  String formatCurrentTime(TimeOfDay cTime) {
4
    final TimeOfDay nowTime = cTime;
5
    String nowTimeString = "${nowTime.hour}:${nowTime.minute}";
6
    return nowTimeString;
7
  }
8
9
  callDatePicker() async {
10
    TimeOfDay resultTime = await selectedTime();
11
    setState(() {
12
      _selectResult = formatCurrentTime(resultTime);
13
      print(_selectResult);
14
    });
15
  }
16
17
  Future<TimeOfDay> selectedTime() {
18
    return showTimePicker(
19
      context: context,
20
      initialTime: TimeOfDay.now(),
21
      builder: (BuildContext context, Widget child) {
22
        return Theme(
23
          data: ThemeData.dark(),
24
          child: child,
25
        );
26
      },
27
    );
28
  }
29
30
  @override
31
  void initState() {
32
    // TODO: implement initState
33
    super.initState();
34
    _selectResult = formatCurrentTime(TimeOfDay.now());
35
  }
36
37
  @override
38
  Widget build(BuildContext context) {
39
    return Scaffold(
40
      appBar: AppBar(
41
        title: Text("HomePage"),
42
      ),
43
      body: Container(
44
          child: Column(
45
            children: <Widget>[
46
              RaisedButton(
47
                child: Text("显示Dialog"),
48
                onPressed: callDatePicker,
49
              ),
50
              Text("$_selectResult"),
51
            ],
52
          ),
53
      ),
54
    );
55
  }
56
}

效果如下:

202041943

上述代码自定义了一个将 TimeOfDay 转换为所需字符串的方法,也可以引入 DateFormat

三、showModalBottomSheet Function

showModalBottomSheet 显示一个模态的从底部弹出的底页。模态底页是菜单或对话框的替代方案,可防止用户与应用程序的其余部分进行交互。

1
Future<T> showModalBottomSheet<T>({
2
  //BuildContext类型必传参数,上下文
3
  @required BuildContext context,
4
  //WidgetBuilder类型必传参数,用于构建子Widget的方法
5
  @required WidgetBuilder builder,
6
  //Color类型可选命名参数,背景色
7
  Color backgroundColor,
8
  //double类型可选命名参数,Z轴坐标
9
  double elevation,
10
  //ShapeBorder类型可选命名参数,边框形状
11
  ShapeBorder shape,
12
  //Clip类型可选命名参数,如何剪裁
13
  Clip clipBehavior,
14
  //bool类型可选命名参数,参数指定这是否是将使用DraggableScrollableSheet的底部工作表的路由。
15
  //如果希望具有可滚动子级(例如ListView或GridView)的底页,并且底页是可拖动的,则应将此参数设置为true。
16
  bool isScrollControlled = false,
17
  //bool类型可选命名参数,参数确保在设置为true时,根导航器用于显示BottomSheet。如果需要在所有其他
18
  //内容上方显示模式BottomSheet,但调用者在另一个Navigator内,则这很有用
19
  bool useRootNavigator = false,
20
  //bool类型可选命名参数,点击模态背景是否关闭底页
21
  bool isDismissible = true,
22
})

使用如下:

1
class _MyHomePageState extends State<MyHomePage> {
2
  @override
3
  Widget build(BuildContext context) {
4
    return Scaffold(
5
      appBar: AppBar(
6
        title: Text("HomePage"),
7
      ),
8
      body: Container(
9
        color: Colors.yellow,
10
          child: RaisedButton(
11
            onPressed: ()=>showModalBottomSheet(
12
              isDismissible: true,
13
              context: context,
14
              builder: (ctx){
15
                return Container(
16
                  height: 400,
17
                );
18
              },
19
            ),
20
          ),
21
      ),
22
    );
23
  }
24
}

效果如下:

2020421104

四、showButtomSheet Function

showButtomSheet 显示最近的 Scaffold 祖先中的设计底页。如果希望显示持久的底部工作表,请使用Scaffold.bottomSheet ,关于 bottomSheet 前面文章介绍过,http://www.mwpush.com/content/950cce6d.html。

该方法返回一个 PersistentBottomSheetController 类型的控制器,可用于关闭和操作底页。要重建底部工作表(例如,如果它是有状态的),请在此方法返回的控制器上调用 PersistentBottomSheetController.setState 。新的底部工作表将成为封闭 ModalRouteLocalHistoryEntry ,并且向后的按钮添加到了脚手架的应用程序栏中,以关闭底部工作表。要创建不是 LocalHistoryEntry 的持久性底页,并且不向封闭的Scaffold的应用程序栏添加后退按钮,请使用 Scaffold.bottomSheet 构造函数参数。

方法定义如下:

1
PersistentBottomSheetController<T> showBottomSheet<T>({
2
  //BuildContext类型必传参数,上下文
3
  @required BuildContext context,
4
  //WidgetBuilder类型必传参数,用于构建子Widget的方法
5
  @required WidgetBuilder builder,
6
  //Color类型可选命名参数,背景色
7
  Color backgroundColor,
8
  //double类型可选命名参数,Z轴坐标
9
  double elevation,
10
  //ShapeBorder类型可选命名参数,边框形状
11
  ShapeBorder shape,
12
  //Clip类型可选命名参数,如何剪裁
13
  Clip clipBehavior,
14
})

使用如下:

1
class _MyHomePageState extends State<MyHomePage> {
2
  @override
3
  Widget build(BuildContext context) {
4
    return Scaffold(
5
      appBar: AppBar(
6
        title: Text("HomePage"),
7
      ),
8
      body: Container(
9
        color: Colors.yellow,
10
          child: Builder(builder: (context){
11
            return RaisedButton(
12
              child: Text("显示"),
13
              onPressed: () {
14
                PersistentBottomSheetController controller = showBottomSheet(
15
                  context: context,
16
                  builder: (context){
17
                    return Container(
18
                      height: 400,
19
                      color: Colors.red,
20
                    );
21
                  },
22
                );
23
              },
24
            );
25
          }),
26
      ),
27
    );
28
  }
29
}

效果如下:

202042123

使用 Scaffold.of() 方法调用如下,

1
class _MyHomePageState extends State<MyHomePage> {
2
  @override
3
  Widget build(BuildContext context) {
4
    return Scaffold(
5
      appBar: AppBar(
6
        title: Text("HomePage"),
7
      ),
8
      body: Container(
9
        color: Colors.yellow,
10
          child: Builder(builder: (context){
11
            return RaisedButton(
12
              child: Text("显示"),
13
              onPressed: () {
14
                Scaffold.of(context).showBottomSheet((context){
15
                  return Container(
16
                    height: 200,
17
                    color: Colors.red,
18
                    child: Center(
19
                      child: FlatButton(
20
                        child: Text("关闭"),
21
                        onPressed: ()=> Navigator.pop(context),
22
                      ),
23
                    ),
24
                  );
25
                });
26
              },
27
            );
28
          }),
29
      ),
30
    );
31
  }
32
}

五、DayPicker Widget

DayPicker 是显示给定月份的日期并允许选择一天的 Widget 。这些天以矩形网格排列,一周的每一天都有一列。此 Widget 很少直接使用。 相反,请考虑使用 showDatePicker ,它会创建一个日期选择器对话框。

构造方法如下:

1
DayPicker({
2
  Key key,
3
  //DateTime类型必传参数,当前选择的日期
4
  @required this.selectedDate,
5
  //DateTime类型必传参数,显示选择器时的当前日期
6
  @required this.currentDate,
7
  //ValueChanged<DateTime>类型必传参数,当用户选择一天时调用的方法
8
  @required this.onChanged,
9
  //DateTime类型必传参数,允许用户选择最早的日期
10
  @required this.firstDate,
11
  //DateTime类型必传参数,允许用户选择的最晚日期
12
  @required this.lastDate,
13
  //DateTime类型必传参数,此选择器显示其日期的月份
14
  @required this.displayedMonth,
15
  //SelectableDayPredicate类型可选命名参数,可选的用户提供的谓词功能可自定义可选日期
16
  this.selectableDayPredicate,
17
  //DragStartBehavior可选命名参数,确定处理拖动开始行为的方式
18
  this.dragStartBehavior = DragStartBehavior.start,
19
})

使用方法如下:

1
class _MyHomePageState extends State<MyHomePage> {
2
  DateTime _currentDate;
3
  @override
4
  void initState() {
5
    // TODO: implement initState
6
    super.initState();
7
    _currentDate = DateTime(2020, 4, 2);
8
  }
9
  @override
10
  Widget build(BuildContext context) {
11
    return Scaffold(
12
      appBar: AppBar(
13
        title: Text("HomePage"),
14
      ),
15
      body: Container(
16
        color: Colors.yellow,
17
          child: DayPicker(
18
            selectedDate: _currentDate,
19
            currentDate: DateTime.now(),
20
            onChanged: (DateTime dateTime){
21
              setState(() {
22
                _currentDate = dateTime;
23
              });
24
            },
25
            firstDate: DateTime(1997),
26
            lastDate: DateTime(2200),
27
            displayedMonth: DateTime.now(),
28
            selectableDayPredicate: (DateTime dateTime) {
29
              if(dateTime.compareTo(DateTime(2020, 4, 5)) < 0) {
30
                return true;
31
              }
32
              return false;
33
            } ,
34
          )
35
      ),
36
    );
37
  }
38
}

效果如下:

2020421003

六、MonthPicker Widget

MonthPicker 是一个可滚动的月份列表,允许选择一个月。在矩形网格中显示每月的某天,一周的每一天都有一列。MonthPicker 很少直接使用,可以考虑使用 showDatePicker ,它会创建一个日期选择器对话框。构造方法如下:

1
MonthPicker({
2
  Key key,
3
  //DateTime类型必传参数,当前选择的日期
4
  @required this.selectedDate,
5
  //ValueChanged<DateTime>类型必传参数,当用户选择年份时调用的方法
6
  @required this.onChanged,
7
  //DateTime类型必传参数,允许用户选择最早的日期
8
  @required this.firstDate,
9
  //DateTime类型必传参数,允许用户选择的最晚日期
10
  @required this.lastDate,
11
  //SelectableDayPredicate类型可选命名参数,可选的用户提供的谓词功能可自定义可选日期
12
  this.selectableDayPredicate,
13
  //DragStartBehavior可选命名参数,确定处理拖动开始行为的方式
14
  this.dragStartBehavior = DragStartBehavior.start,
15
}

使用如下:

1
class _MyHomePageState extends State<MyHomePage> {
2
  DateTime _currentDate;
3
  @override
4
  void initState() {
5
    // TODO: implement initState
6
    super.initState();
7
    _currentDate = DateTime(2020, 4, 2);
8
  }
9
  @override
10
  Widget build(BuildContext context) {
11
    return Scaffold(
12
      appBar: AppBar(
13
        title: Text("HomePage"),
14
      ),
15
      body: Container(
16
        color: Colors.yellow,
17
          child: MonthPicker(					//MonthPicker
18
            selectedDate: _currentDate,
19
            onChanged: (DateTime dateTime){
20
              setState(() {
21
                _currentDate = dateTime;
22
              });
23
            },
24
            firstDate: DateTime(1997),
25
            lastDate: DateTime(2200),
26
            selectableDayPredicate: (DateTime dateTime) {
27
              if(dateTime.compareTo(DateTime(2020, 4, 5)) < 0) {
28
                return true;
29
              }
30
              return false;
31
            } ,
32
          )
33
      ),
34
    );
35
  }
36
}

效果如下:

202042959

七、YearPicker Widget

YearPicker 是一个可滚动的年份列表,允许选择年份。YearPicker 很少直接使用,可以考虑使用 showDatePicker 它会创建一个日期选择器对话框。 构造方法如下:

1
YearPicker({
2
  Key key,
3
  //DateTime类型必传参数,当前选择的日期
4
  @required this.selectedDate,
5
  //ValueChanged<DateTime>类型必传参数,当用户选择年份时调用的方法
6
  @required this.onChanged,
7
  //DateTime类型必传参数,允许用户选择最早的日期
8
  @required this.firstDate,
9
  //DateTime类型必传参数,允许用户选择的最晚日期
10
  @required this.lastDate,
11
  //DragStartBehavior可选命名参数,确定处理拖动开始行为的方式
12
  this.dragStartBehavior = DragStartBehavior.start,
13
})

使用如下:

1
class _MyHomePageState extends State<MyHomePage> {
2
  DateTime _currentDate;
3
  @override
4
  void initState() {
5
    // TODO: implement initState
6
    super.initState();
7
    _currentDate = DateTime(2020);
8
  }
9
  @override
10
  Widget build(BuildContext context) {
11
    return Scaffold(
12
      appBar: AppBar(
13
        title: Text("HomePage"),
14
      ),
15
      body: Container(
16
        color: Colors.yellow,
17
          child: YearPicker(
18
            selectedDate: _currentDate,
19
            onChanged: (DateTime dateTime){
20
              setState(() {
21
                _currentDate = dateTime;
22
              });
23
            },
24
            firstDate: DateTime(1997),
25
            lastDate: DateTime(2200),
26
          )
27
      ),
28
    );
29
  }
30
}

效果如下:

202042938

八、ExpansionPanelList Widget

ExpansionPanelList 是一个扩展列表,其中列出了其子级并为扩展设置了动画效果。ExpansionPanelList 必须包含在主轴可以无限扩展的 Widget 中。构造方法如下:

1
//创建一个扩展面板列表小部件。当按下扩展面板的扩展/折叠按钮时,会触发expandingCallback
2
const ExpansionPanelList({
3
  Key key,
4
  //List<ExpansionPanel>类型可选命名参数,扩展面板的子级列表。它们的布局与ListBody相似。
5
  this.children = const <ExpansionPanel>[],
6
  //ExpansionPanelCallback类型可选命名参数,按下扩展/折叠按钮之一时将调用的回调
7
  //传递给回调的参数是所按面板的索引以及面板当前是否展开
8
  this.expansionCallback,
9
  //Duration类型可选命名参数,扩展动画的持续时间
10
  this.animationDuration = kThemeAnimationDuration,
11
})
12
  
13
//创建一个Radio扩展面板列表小部件
14
const ExpansionPanelList.radio({
15
  Key key,
16
  //List<ExpansionPanelRadio>类型可选命名参数,扩展面板的子级列表。
17
  this.children = const <ExpansionPanelRadio>[],
18
  ///传递给回调的参数是所按面板的索引以及面板当前是否展开
19
  this.expansionCallback,
20
  ////Duration类型可选命名参数,扩展动画的持续时间
21
  this.animationDuration = kThemeAnimationDuration,
22
  //Object类型可选命名参数,最初开始打开的面板的值。
23
  this.initialOpenPanelValue,
24
})

ExpansionPanel 是扩展面板。 它具有标题和主体,可以扩展或折叠。 面板的主体只有在展开时才可见。其用于 ExpansionPanelList 的子 Widget 。构造方法如下:

1
ExpansionPanel({
2
  //ExpansionPanelHeaderBuilder类型必传参数,构建扩展面板标题的窗口小部件构建器
3
  @required this.headerBuilder,
4
  //Widget类型必传参数,标头下方显示的扩展面板的主体
5
  @required this.body,
6
  //bool类型可选命名参数,点击面板标题是否会展开/折叠
7
  this.isExpanded = false,
8
  //bool类型可选命名参数,面板是否展开
9
  this.canTapOnHeader = false,
10
})

ExpansionPanelHeaderBuilder 是一个返回值为 Widget 的方法,定义为:Widget Function(BuildContext context, bool isExpanded)

ExpansionPanelRadio 是一个最多只能有一项面板可以展开的扩展面板。必须为每个面板分配唯一的标识符值。 该标识符允许 ExpansionPanelList 确定应扩展哪个 ExpansionPanelRadio 实例。构造方法如下:

1
ExpansionPanelRadio({
2
  //Object类型必传参数,该值唯一地标识一个Radio面板,以便可以标识当前选择的Radio面板。
3
  @required this.value,
4
  //ExpansionPanelHeaderBuilder类型必传参数,构建扩展面板标题的窗口小部件构建器
5
  @required ExpansionPanelHeaderBuilder headerBuilder,
6
  //Widget类型必传参数,标头下方显示的扩展面板的主体
7
  @required Widget body,
8
  //bool类型可选命名参数,点击面板标题是否会展开/折叠
9
  bool canTapOnHeader = false,
10
})

ExpansionPanelList 实现方式如下:

1
class _MyHomePageState extends State<MyHomePage> {
2
  final List<String> _itemTitles = <String>[
3
    "联系人",
4
    "分组",
5
    "黑名单"
6
  ];
7
8
  List<ExpandItem> _generateItems(int itemsCount) {
9
    return List.generate(itemsCount, (int index){
10
      return ExpandItem(_itemTitles[index], false);
11
    });
12
  }
13
14
  List<ExpandItem> _resultData;
15
  @override
16
  void initState() {
17
    super.initState();
18
    _resultData = _generateItems(_itemTitles.length);
19
  }
20
21
  @override
22
  Widget build(BuildContext context) {
23
    return Scaffold(
24
      appBar: AppBar(
25
        title: Text("HomePage"),
26
      ),
27
      body:  SingleChildScrollView(
28
        child: ExpansionPanelList(				//ExpansionPanelList
29
          children: _resultData.map<ExpansionPanel>((ExpandItem item){
30
            return ExpansionPanel(
31
              canTapOnHeader: true,
32
              headerBuilder: (BuildContext context, bool expanded){
33
                return Container(
34
                  padding: EdgeInsets.only(left: 20),
35
                  alignment: Alignment.centerLeft,
36
                  height: 80,
37
                  child: Text("${item.title}"),
38
                );
39
              },
40
              body: Container(
41
                height: 100,
42
                color: Colors.yellow,
43
              ),
44
              isExpanded: item.isExpanded,
45
            );
46
          }).toList(),
47
          expansionCallback: (int panelIndex, bool isExpanded){
48
            setState(() {
49
              _resultData[panelIndex].isExpanded = !isExpanded;
50
            });
51
          },
52
        ),
53
      ),
54
    );
55
  }
56
}

效果如下:

202042353

ExpansionPanelRadio 使用方法如下:

1
class _MyHomePageState extends State<MyHomePage> {
2
  final List<String> _itemTitles = <String>[
3
    "联系人",
4
    "分组",
5
    "黑名单"
6
  ];
7
8
  List<ExpandItem> _generateItems(int itemsCount) {
9
    return List.generate(itemsCount, (int index){
10
      return ExpandItem(_itemTitles[index], false, index);
11
    });
12
  }
13
14
  List<ExpandItem> _resultData;
15
  @override
16
  void initState() {
17
    super.initState();
18
    _resultData = _generateItems(_itemTitles.length);
19
  }
20
21
  @override
22
  Widget build(BuildContext context) {
23
    return Scaffold(
24
      appBar: AppBar(
25
        title: Text("HomePage"),
26
      ),
27
      body:  SingleChildScrollView(
28
        child: ExpansionPanelList.radio(
29
          initialOpenPanelValue: 2,
30
          children: _resultData.map<ExpansionPanelRadio>((ExpandItem item){
31
            return ExpansionPanelRadio(
32
              value: item.id,
33
              canTapOnHeader: true,
34
              headerBuilder: (BuildContext context, bool expanded){
35
                return Container(
36
                  padding: EdgeInsets.only(left: 20),
37
                  alignment: Alignment.centerLeft,
38
                  height: 80,
39
                  child: Text("${item.title}"),
40
                );
41
              },
42
              body: Container(
43
                height: 100,
44
                color: Colors.yellow,
45
              ),
46
            );
47
          }).toList(),
48
          expansionCallback: (int panelIndex, bool isExpanded){
49
            setState(() {
50
              _resultData[panelIndex].isExpanded = !isExpanded;
51
            });
52
          },
53
        ),
54
      ),
55
    );
56
  }
57
}
58
59
class ExpandItem {
60
  ExpandItem(this.title, this.isExpanded, this.id);
61
  int id;
62
  String title;
63
  bool isExpanded;
64
}

效果如下:

202042354
陌问.MW wechat
欢迎关注微信公众号,及时获取知识!