老孟导读:Flutter 1.20 更新了 Slider、RangeSlider、日期选择器组件、工夫选择器组件的款式,新增了替换组件:InteractiveViewer,上面具体介绍其用法。
滑块
Flutter 1.20 版本将 Slider 和 RangeSlider 小部件更新为最新的 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
RangeSlider 和 Slider 简直一样,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
结构图
- 题目
- 选中的日期
- 切换到输出模式
- 年抉择菜单
- 月份分页
- 以后工夫
- 选中日期
输出模式 结构图:
- 题目
- 选中日期
- 切换 日历模式
- 输入框
根底用法
点击按钮弹出日期组件:
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,);
间接显示 输出模式,默认是日历模式。
设置日历日期选择器的初始显示,蕴含 day 和 year:
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 一样。
范畴日期结构图:
- 题目
- 选定的日期范畴
- 切换到输出模式
- 月和年标签
- 以后工夫
- 开始工夫
- 选中工夫范畴
- 完结工夫
国际化
国际化都是一个套路,上面以 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'),)
maxScale 、minScale、scaleEnabled 是缩放相干参数,别离示意最大缩放倍数、最小缩放倍数、是否能够缩放:
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】: