共计 14325 个字符,预计需要花费 36 分钟才能阅读完成。
老孟导读: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】: