老孟导读:Flutter 1.20 更新了 Slider、RangeSlider、日期选择器组件、工夫选择器组件的款式,新增了替换组件:InteractiveViewer,上面具体介绍其用法。

滑块

Flutter 1.20 版本将 SliderRangeSlider 小部件更新为最新的 Material 准则。新的滑块在设计时思考到了更好的可拜访性:轨道更高,滑块带有暗影,并且值指示器具备新的形态和改良的文本缩放反对。

Slider

根底用法:

class SliderDemo extends StatefulWidget {  @override  _SliderDemoState createState() => _SliderDemoState();}class _SliderDemoState extends State<SliderDemo> {  double _sliderValue = 0;  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(),      body: Center(        child: Column(          mainAxisSize: MainAxisSize.min,          children: [            Text('值:$_sliderValue'),            Slider(              value: _sliderValue,              onChanged: (v){                setState(() {                  _sliderValue = v;                });              },            )          ],        ),      ),    );  }}
  • value:以后值。
  • onChanged:滑块值扭转时回调。

看看 Flutter 1.20 版本以前的款式(我的收藏):

显著的感觉就是滑块轨道变粗了,滑块变的更有立体感(加了暗影)了。

Slider 默认滑动范畴是 0-1,批改为 1-100:

Slider(  value: _sliderValue,  min: 1,  max: 100,  onChanged: (v){    setState(() {      _sliderValue = v;    });  },)

设置滑块的滑动为 离散的,即滑动值为 0、25 、50、75 100:

Slider(  value: _sliderValue,  min: 0,  max: 100,  divisions: 4,  onChanged: (v){    setState(() {      _sliderValue = v;    });  },)

设置标签,滑动过程中在其上方显示:

Slider(  value: _sliderValue,  label: '$_sliderValue',  min: 0,  max: 100,  divisions: 4,  onChanged: (v){    setState(() {      _sliderValue = v;    });  },)

看看 Flutter 1.20 版本以前的款式(仍然是我的收藏):

个人感觉以前的更好看。

上面是官网给的 Slider 结构图:

  • 1 :轨道(Track),1 和 4 是有区别的,1 指的是底部整个轨道,轨道显示了可供用户抉择的范畴。对于从左到右(LTR)的语言,最小值呈现在轨道的最左端,而最大值呈现在最右端。对于从右到左(RTL)的语言,此方向是相同的。
  • 2:滑块(Thumb),地位指示器,能够沿着轨道挪动,显示其地位的选定值。
  • 3:标签(label),显示与滑块的地位绝对应的特定数字值。
  • 4:刻度指示器(Tick mark),示意用户能够将滑块挪动到的预约值。

自定义滑块 激活的色彩未激活的色彩

Slider(  activeColor: Colors.red,  inactiveColor: Colors.blue,  value: _sliderValue,  label: '$_sliderValue',  min: 0,  max: 100,  divisions: 4,  onChanged: (v){    setState(() {      _sliderValue = v;    });  },)

这个自定义比拟抽象,上面来一个更粗疏的自定义:

SliderTheme(  data: SliderTheme.of(context).copyWith(      activeTrackColor: Color(0xff404080),      thumbColor: Colors.blue,      overlayColor: Colors.green,      valueIndicatorColor: Colors.purpleAccent),  child: Slider(    value: _sliderValue,    label: '$_sliderValue',    min: 0,    max: 100,    divisions: 4,    onChanged: (v) {      setState(() {        _sliderValue = v;      });    },  ),)

这个根本能够齐全自定义款式了。

如何在 Flutter 1.20 版本应用以前的标签款式呢?

SliderTheme(  data: SliderTheme.of(context).copyWith(    valueIndicatorShape: PaddleSliderValueIndicatorShape(),  ),  child: Slider(    value: _sliderValue,    label: '$_sliderValue',    min: 0,    max: 100,    divisions: 4,    onChanged: (v) {      setState(() {        _sliderValue = v;      });    },  ),)

RectangularSliderValueIndicatorShape 示意矩形款式:

RangeSlider

RangeSliderSlider 简直一样,RangeSlider 是范畴滑块,想要抉择一段值,能够应用 RangeSlider。

RangeValues _rangeValues = RangeValues(0, 25);RangeSlider(  values: _rangeValues,  labels: RangeLabels('${_rangeValues.start}','${_rangeValues.end}'),  min: 0,  max: 100,  divisions: 4,  onChanged: (v) {    setState(() {      _rangeValues = v;    });  },),

滑块状态

ios格调的 Slider

ios格调的 Slider,应用 CupertinoSlider:

double _sliderValue = 0;CupertinoSlider(  value: _sliderValue,  onChanged: (v) {    setState(() {      _sliderValue = v;    });  },)

当然也能够依据平台显示不同格调的Slider,ios平台显示CupertinoSlider成果,其余平台显示Material格调,用法如下:

Slider.adaptive(  value: _sliderValue,  onChanged: (v) {    setState(() {      _sliderValue = v;    });  },)

Material格调日期选择器

Flutter 1.20 版本更新了 日期 类组件的款式,退出了新的紧凑设计以及对日期范畴的反对。

showDatePicker

结构图

  1. 题目
  2. 选中的日期
  3. 切换到输出模式
  4. 抉择菜单
  5. 月份分页
  6. 以后工夫
  7. 选中日期

输出模式 结构图:

  1. 题目
  2. 选中日期
  3. 切换 日历模式
  4. 输入框

根底用法

点击按钮弹出日期组件:

 RaisedButton(          child: Text('弹出日期组件'),          onPressed: () async {            await showDatePicker(              context: context,              initialDate: DateTime.now(),              firstDate: DateTime(2010),              lastDate: DateTime(2025),            );

  • initialDate:初始化工夫,通常状况下设置为以后工夫。
  • firstDate:示意开始工夫,不能抉择此工夫后面的工夫。
  • lastDate:示意完结工夫,不能抉择此工夫之后的工夫。

设置日期选择器对话框的模式:

var result = await showDatePicker(  context: context,  initialDate: DateTime.now(),  firstDate: DateTime(2010),  lastDate: DateTime(2025),  initialEntryMode: DatePickerEntryMode.input,);

间接显示 输出模式,默认是日历模式

设置日历日期选择器的初始显示,蕴含 dayyear

var result = await showDatePicker(  context: context,  initialDate: DateTime.now(),  firstDate: DateTime(2010),  lastDate: DateTime(2025),  initialDatePickerMode: DatePickerMode.year,);

和以前的版本比照:

设置顶部题目、勾销按钮、确定按钮 文案:

var result = await showDatePicker(  context: context,  initialDate: DateTime.now(),  firstDate: DateTime(2010),  lastDate: DateTime(2025),  helpText: '选则日期',  cancelText: '勾销',  confirmText: '确定',);

批改 输出模式 下文案:

var result = await showDatePicker(  context: context,  initialDate: DateTime.now(),  firstDate: DateTime(2010),  lastDate: DateTime(2025),  errorFormatText: '谬误的日期格局',  errorInvalidText: '日期格局非法',  fieldHintText: '月/日/年',  fieldLabelText: '填写日期',);

设置可选日期范畴

var result = await showDatePicker(  context: context,  initialDate: DateTime.now(),  firstDate: DateTime(2010),  lastDate: DateTime(2025),  selectableDayPredicate: (date) {    return date.difference(DateTime.now()).inMilliseconds < 0;  },);

明天当前的日期全副为灰色,不可选状态。

设置深色主题

设置深色主题使 builder ,其用于包装对话框窗口小部件以增加继承的窗口小部件,例如Theme,设置深色主题如下:

var result = await showDatePicker(  context: context,  initialDate: DateTime.now(),  firstDate: DateTime(2010),  lastDate: DateTime(2025),  builder: (context,child){    return Theme(      data: ThemeData.dark(),      child: child,    );  });

获取选中的日期

showDatePicker 办法是 Future 办法,点击日期抉择控件的确定按钮后,返回抉择的日期。

var result = await showDatePicker(              context: context,              initialDate: DateTime.now(),              firstDate: DateTime(2010),              lastDate: DateTime(2025),            );print('$result');

result 为抉择的日期。

CalendarDatePicker

日期组件间接显示在页面上,而不是弹出显示:

CalendarDatePicker(  initialDate: DateTime.now(),  firstDate: DateTime(2010),  lastDate: DateTime(2025),  onDateChanged: (d) {    print('$d');  },)

其参数和 showDatePicker 一样。

范畴日期

抉择范畴日期应用 showDateRangePicker

RaisedButton(  child: Text('范畴日期'),  onPressed: () async {    var date = showDateRangePicker(context: context, firstDate: DateTime(2010), lastDate: DateTime(2025));  },),

其参数和 showDatePicker 一样。

范畴日期结构图:

  1. 题目
  2. 选定的日期范畴
  3. 切换到输出模式
  4. 月和年标签
  5. 以后工夫
  6. 开始工夫
  7. 选中工夫范畴
  8. 完结工夫

国际化

国际化都是一个套路,上面以 showDatePicker 为例:

pubspec.yaml 中引入:

dependencies:  flutter_localizations:    sdk: flutter

在顶级组件 MaterialApp 增加反对:

MaterialApp(  title: 'Flutter Demo',  localizationsDelegates: [    GlobalMaterialLocalizations.delegate,    GlobalWidgetsLocalizations.delegate,    GlobalCupertinoLocalizations.delegate,  ],  supportedLocales: [    const Locale('zh'),    const Locale('en'),  ],  ...

弹出日期组件:

var result = await showDatePicker(  context: context,  initialDate: DateTime.now(),  firstDate: DateTime(2010),  lastDate: DateTime(2025),);

此时将零碎语音调整为中文

此组件只反对中文,不论零碎设置语言:

var result = await showDatePicker(  context: context,  initialDate: DateTime.now(),  firstDate: DateTime(2010),  lastDate: DateTime(2025),  locale: Locale('zh'));

Material格调工夫选择器

Flutter 1.20 版本更新了 工夫 类组件的款式。

根底应用

弹出工夫组件:

RaisedButton(  child: Text('弹出工夫选择器'),  onPressed: () async {    var result =        showTimePicker(context: context, initialTime: TimeOfDay.now());  },)

1.20 版以前的成果:

设置 交互模式,交互模式蕴含 时钟模式(默认)和 输出模式

var result = showTimePicker(    context: context,    initialTime: TimeOfDay.now(),    initialEntryMode: TimePickerEntryMode.input);

时钟模式(TimePickerEntryMode.dial):

输出模式(TimePickerEntryMode.input):

设置顶部题目、勾销按钮、确定按钮 文案:

var result = showTimePicker(    context: context,    initialTime: TimeOfDay.now(),    initialEntryMode: TimePickerEntryMode.input,    helpText: '抉择工夫',    cancelText: '勾销',    confirmText: '确定');

24小时 制:

var result = showTimePicker(  context: context,  initialTime: TimeOfDay.now(),  builder: (BuildContext context, Widget child) {    return MediaQuery(      data: MediaQuery.of(context)          .copyWith(alwaysUse24HourFormat: true),      child: child,    );  },);

光明模式

var result = showTimePicker(  context: context,  initialTime: TimeOfDay.now(),  builder: (BuildContext context, Widget child) {    return Theme(      data: ThemeData.dark(),      child: child,    );  },);

国际化

pubspec.yaml 中引入:

dependencies:  flutter_localizations:    sdk: flutter

在顶级组件 MaterialApp 增加反对:

MaterialApp(  title: 'Flutter Demo',  localizationsDelegates: [    GlobalMaterialLocalizations.delegate,    GlobalWidgetsLocalizations.delegate,    GlobalCupertinoLocalizations.delegate,  ],  supportedLocales: [    const Locale('zh'),    const Locale('en'),  ],  ...

弹出工夫组件:

RaisedButton(  child: Text('弹出工夫选择器'),  onPressed: () async {    var result =        showTimePicker(context: context, initialTime: TimeOfDay.now());  },)

切换零碎语言为中文:

不追随零碎语言,间接指定,比方以后零碎语言为中文,指定为英文:

var result = showTimePicker(  context: context,  initialTime: TimeOfDay.now(),  builder: (BuildContext context, Widget child) {    return Localizations(      locale: Locale('en'),      delegates: [        GlobalMaterialLocalizations.delegate,        GlobalWidgetsLocalizations.delegate,      ],      child: child,    );  },);

iOS格调日期选择器

根底应用

CupertinoDatePicker 是 iOS格调的日期选择器。

class CupertinoDatePickerDemo extends StatefulWidget {  @override  _CupertinoDatePickerDemoState createState() => _CupertinoDatePickerDemoState();}class _CupertinoDatePickerDemoState extends State<CupertinoDatePickerDemo> {  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(),      body: Center(        child: Container(          height: 200,          color: Colors.grey.withOpacity(.5),          child: CupertinoDatePicker(            initialDateTime: DateTime.now(),            onDateTimeChanged: (date) {              print('$date');            },          ),        ),      ),    );  }}

设置最大/小工夫:

CupertinoDatePicker(  initialDateTime: DateTime.now(),  minimumDate: DateTime.now().add(Duration(days: -1)),  maximumDate: DateTime.now().add(Duration(days: 1)),  onDateTimeChanged: (date) {    print('$date');  },)

最大工夫为今天,最小工夫为昨天:

设置模式为工夫

CupertinoDatePicker(  mode: CupertinoDatePickerMode.time,  initialDateTime: DateTime.now(),  onDateTimeChanged: (date) {    print('$date');  },)

设置模式为日期

CupertinoDatePicker(  mode: CupertinoDatePickerMode.date,  initialDateTime: DateTime.now(),  onDateTimeChanged: (date) {    print('$date');  },)

设置模式为日期和工夫

CupertinoDatePicker(  mode: CupertinoDatePickerMode.dateAndTime,  initialDateTime: DateTime.now(),  onDateTimeChanged: (date) {    print('$date');  },)

  • time:只显示工夫,成果:4 | 14 | PM
  • date:只显示日期,成果:July | 13 | 2012
  • dateAndTime:工夫和日期都显示,成果: Fri Jul 13 | 4 | 14 | PM

应用24小时制:

CupertinoDatePicker(  use24hFormat: true,  initialDateTime: DateTime.now(),  onDateTimeChanged: (date) {    print('$date');  },)

国际化

pubspec.yaml 中引入:

dependencies:  flutter_localizations:    sdk: flutter

在顶级组件 MaterialApp 增加反对:

MaterialApp(  title: 'Flutter Demo',  localizationsDelegates: [    GlobalMaterialLocalizations.delegate,    GlobalWidgetsLocalizations.delegate,    GlobalCupertinoLocalizations.delegate,  ],  supportedLocales: [    const Locale('zh'),    const Locale('en'),  ],  ...

组件应用:

CupertinoDatePicker(  initialDateTime: DateTime.now(),  onDateTimeChanged: (date) {    print('$date');  },)

组件语言追随零碎语言,以后零碎语言为英文,成果:

不追随零碎语言,间接指定,比方以后零碎语言为英文,指定为中文:

Localizations(  locale: Locale('zh'),  delegates: [    GlobalMaterialLocalizations.delegate,    GlobalWidgetsLocalizations.delegate,    GlobalCupertinoLocalizations.delegate,  ],  child: CupertinoDatePicker(    initialDateTime: DateTime.now(),    onDateTimeChanged: (date) {      print('$date');    },  ),)

iOS格调工夫选择器

根底应用

CupertinoTimerPicker 是 iOS格调的工夫选择器。

CupertinoTimerPicker(onTimerDurationChanged: (time) {  print('$time');})

设置显示模式:

  • CupertinoTimerPickerMode.hm:显示 小时 | 分钟,英文成果16 hours | 14 min
  • CupertinoTimerPickerMode.ms: 显示 分钟 | 秒,英文成果14 min | 43 sec
  • CupertinoTimerPickerMode.hms:显示 小时 | 分钟 | 秒,英文成果16 hours | 14 min | 43 sec
CupertinoTimerPicker(    mode: CupertinoTimerPickerMode.hm,    onTimerDurationChanged: (time) {      print('$time');    })

默认状况下,CupertinoTimerPicker显示0:0:0,设置显示以后工夫:

CupertinoTimerPicker(    initialTimerDuration: Duration(        hours: DateTime.now().hour,        minutes: DateTime.now().minute,        seconds: DateTime.now().second),    onTimerDurationChanged: (time) {      print('$time');    })

设置 分/秒 的距离:

CupertinoTimerPicker(    minuteInterval: 5,    secondInterval: 5,    onTimerDurationChanged: (time) {      print('$time');    })

国际化

pubspec.yaml 中引入:

dependencies:  flutter_localizations:    sdk: flutter

在顶级组件 MaterialApp 增加反对:

MaterialApp(  title: 'Flutter Demo',  localizationsDelegates: [    GlobalMaterialLocalizations.delegate,    GlobalWidgetsLocalizations.delegate,    GlobalCupertinoLocalizations.delegate,  ],  supportedLocales: [    const Locale('zh'),    const Locale('en'),  ],  ...

组件应用:

CupertinoTimerPicker(onTimerDurationChanged: (time) {  print('$time');})

组件语言追随零碎语言,以后零碎语言为英文,成果:

不追随零碎语言,间接指定,比方以后零碎语言为英文,指定为中文:

Localizations(  locale: Locale('zh'),  delegates: [    GlobalMaterialLocalizations.delegate,    GlobalWidgetsLocalizations.delegate,    GlobalCupertinoLocalizations.delegate,  ],  child: CupertinoTimerPicker(onTimerDurationChanged: (time) {    print('$time');  }),)

InteractiveViewer

InteractiveViewer 是 Flutter 1.20 新增的组件,用户能够通过拖动以平移、缩放和拖放子组件。

InteractiveViewer(  child: Image.asset('assets/images/go_board_09x09.png'),)

alignPanAxis 参数示意是否只在程度和垂直方向上拖拽,默认为false,设置为true,无奈沿着对角线(斜着)方向挪动。

InteractiveViewer(  alignPanAxis: true,  child: Image.asset('assets/images/go_board_09x09.png'),)

maxScaleminScalescaleEnabled 是缩放相干参数,别离示意最大缩放倍数、最小缩放倍数、是否能够缩放:

InteractiveViewer(  maxScale: 2,  minScale: 1,  scaleEnabled: true,  child: Image.asset('assets/images/go_board_09x09.png'),)

constrained 参数示意组件树中的束缚是否利用于子组件,默认为true,如果设为true,示意子组件是无限度束缚,这对子组件的尺寸比 InteractiveViewer 大时十分有用,比方子组件为滚动系列组件。

如下的案例,子组件为 Table,Table 尺寸大于屏幕,必须将constrained设置为 false 以便将其绘制为残缺尺寸。超出的屏幕尺寸能够平移到视图中。

class InteractiveViewerDemo extends StatelessWidget {  @override  Widget build(BuildContext context) {    const int _rowCount = 20;    const int _columnCount = 10;    return Scaffold(      appBar: AppBar(),      body: Center(        child: Container(          height: 300,          width: 300,          child: InteractiveViewer(            constrained: false,            child: Table(              columnWidths: <int, TableColumnWidth>{                for (int column = 0; column < _columnCount; column += 1)                  column: const FixedColumnWidth(100.0),              },              children: <TableRow>[                for (int row = 0; row < _rowCount; row += 1)                  TableRow(                    children: <Widget>[                      for (int column = 0; column < _columnCount; column += 1)                        Container(                          height: 50,                          color: row % 2 + column % 2 == 1                              ? Colors.red                              : Colors.green,                        ),                    ],                  ),              ],            ),          ),        ),      ),    );  }}

回调事件:

  • onInteractionStart:当用户开始平移或缩放手势时调用。
  • onInteractionUpdate:当用户更新组件上的平移或缩放手势时调用。
  • onInteractionEnd:当用户在组件上完结平移或缩放手势时调用。
InteractiveViewer(  child: Image.asset('assets/images/go_board_09x09.png'),  onInteractionStart: (ScaleStartDetails scaleStartDetails){    print('onInteractionStart:$scaleStartDetails');  },  onInteractionUpdate: (ScaleUpdateDetails scaleUpdateDetails){    print('onInteractionUpdate:$scaleUpdateDetails');  },  onInteractionEnd: (ScaleEndDetails endDetails){    print('onInteractionEnd:$endDetails');  },)

通过 Matrix4 矩阵对其进行变换,比方左移、放大等,增加变换控制器:

final TransformationController _transformationController =      TransformationController();InteractiveViewer(  child: Image.asset('assets/images/go_board_09x09.png'),  transformationController: _transformationController,)

放大变换:

var matrix = _transformationController.value.clone();matrix.scale(1.5, 1.0, 1.0);_transformationController.value = matrix;

残缺代码:

import 'dart:math';import 'package:flutter/material.dart';////// desc:///class InteractiveViewerDemo extends StatefulWidget {  @override  _InteractiveViewerDemoState createState() => _InteractiveViewerDemoState();}class _InteractiveViewerDemoState extends State<InteractiveViewerDemo> {  final TransformationController _transformationController =      TransformationController();  @override  Widget build(BuildContext context) {    return Scaffold(      appBar: AppBar(),      body: Column(        children: [          Container(            padding: EdgeInsets.symmetric(horizontal: 10.0),            child: Center(              child: InteractiveViewer(                child: Image.asset('assets/images/go_board_09x09.png'),                transformationController: _transformationController,              ),            ),          ),          Expanded(            child: Container(),          ),          Row(            children: [              RaisedButton(                child: Text('重置'),                onPressed: () {                  _transformationController.value = Matrix4.identity();                },              ),              RaisedButton(                child: Text('左移'),                onPressed: () {                  var matrix = _transformationController.value.clone();                  matrix.translate(-5.0);                  _transformationController.value = matrix;                },              ),              RaisedButton(                child: Text('放大'),                onPressed: () {                  var matrix = _transformationController.value.clone();                  matrix.scale(1.5, 1.0, 1.0);                  _transformationController.value = matrix;                },              ),            ],          ),        ],      ),    );  }}

交换

老孟Flutter博客地址(330个控件用法):http://laomengit.com

欢送退出Flutter交换群(微信:laomengit)、关注公众号【老孟Flutter】: