forked from lxm_flutter/FlutterUnit
✨ ModalBarrier、AnimatedModalBarrier、DefaultAssetBundle、DropdownButtonFormField、FormField、InheritedWidget、PaginatedDataTable
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'dart:ui' as ui;
|
||||
/// create by 张风捷特烈 on 2020-04-01
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明: 320 DefaultAssetBundle 默认资源包
|
||||
/// 一个 InheritedWidget,设置 AssetBundle 对象后,该节点后的节点上下文可以通过 DefaultAssetBundle.of(context) 获取 AssetBundle 对象用于访问资源文件。
|
||||
// {
|
||||
// "widgetId": 320,
|
||||
// "name": 'DefaultAssetBundle 介绍',
|
||||
// "priority": 1,
|
||||
// "subtitle":
|
||||
// "【bundle】 : *资源包 【AssetBundle】\n"
|
||||
// "【child】 : *子组件 【Widget】\n"
|
||||
// "我们可以定义自己的 DefaultAssetBundle 来供后续节点使用,也可以直接使用默认的。该案例演示通过框架提供的 DefaultAssetBundle 加载一张资源图片进行显示。",
|
||||
// }
|
||||
class DefaultAssetBundleDemo extends StatefulWidget {
|
||||
@override
|
||||
_DefaultAssetBundleDemoState createState() => _DefaultAssetBundleDemoState();
|
||||
}
|
||||
|
||||
class _DefaultAssetBundleDemoState extends State<DefaultAssetBundleDemo> {
|
||||
ui.Image _image;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_load();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Container(
|
||||
width: 150,
|
||||
height: 150,
|
||||
color: Colors.blue.withOpacity(0.1),
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.all(10),
|
||||
child: _image==null?Container():RawImage(image: _image,fit: BoxFit.cover,),
|
||||
);
|
||||
}
|
||||
|
||||
void _load() async{
|
||||
AssetBundle info = DefaultAssetBundle.of(context);
|
||||
ByteData data = await info.load('assets/images/sabar.webp');
|
||||
_image = await decodeImageFromList(data.buffer.asUint8List());
|
||||
setState(() {
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -36,24 +36,24 @@ class TestBody extends StatelessWidget {
|
||||
margin: EdgeInsets.only(left: 40,right: 40),
|
||||
alignment: Alignment.center,
|
||||
color: Theme.of(context).primaryColor.withOpacity(0.1),
|
||||
child: Text('点我进入下页')));
|
||||
child: Text('InheritedTheme')));
|
||||
}
|
||||
|
||||
void _toNextPage(BuildContext context) {
|
||||
final NavigatorState navigator = Navigator.of(context);
|
||||
final CapturedThemes themes =
|
||||
InheritedTheme.capture(from: context, to: navigator.context);
|
||||
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (BuildContext _) {
|
||||
return themes.wrap(Container(
|
||||
alignment: Alignment.center,
|
||||
color: Colors.white,
|
||||
child: Text('Flutter Unit'),
|
||||
));
|
||||
},
|
||||
),
|
||||
);
|
||||
// final NavigatorState navigator = Navigator.of(context);
|
||||
// final CapturedThemes themes =
|
||||
// InheritedTheme.capture(from: context, to: navigator.context);
|
||||
//
|
||||
// Navigator.of(context).push(
|
||||
// MaterialPageRoute(
|
||||
// builder: (BuildContext _) {
|
||||
// return themes.wrap(Container(
|
||||
// alignment: Alignment.center,
|
||||
// color: Colors.white,
|
||||
// child: Text('Flutter Unit'),
|
||||
// ));
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020/9/21
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明: 346 InheritedWidget 传承组件
|
||||
/// 该类是抽象类,作用是可以在本上下文存储数据,在其后续节点的上下文中共享该数据。有很多实现类,包括各种主题组件、MediaQuery等。
|
||||
/// link: 167,319,328,324,331
|
||||
///
|
||||
// {
|
||||
// "widgetId": 346,
|
||||
// "name": 'InheritedWidget 使用',
|
||||
// "priority": 1,
|
||||
// "subtitle":
|
||||
// "【child】 : 子组件 【Widget】\n"
|
||||
// "下面是一个简单的自定义 InheritedWidget,实现信息的子树共享。",
|
||||
// }
|
||||
|
||||
class InheritedWidgetDemo extends StatelessWidget {
|
||||
final String info =
|
||||
'InheritedWidget 是一个抽象类,不可以直接使用。可以自定义对应共享数据的子类,如这里的通过 InfoInheritedWidget 实现:当前这段话可以在任意子树节点上下文获取。'
|
||||
'一般都会定义一个 XXX.of(context) 的方法来获取数据,如 MediaQuery.of,Theme.of 等。';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InfoInheritedWidget(
|
||||
info: info,
|
||||
child: InfoWidget(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class InfoWidget extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
String info = InfoInheritedWidget.of(context).info;
|
||||
|
||||
return Container(
|
||||
color: Colors.blue.withOpacity(0.1),
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.all(10),
|
||||
child: Text(info),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class InfoInheritedWidget extends InheritedWidget {
|
||||
final String info;
|
||||
|
||||
InfoInheritedWidget({Key key, this.info, @required Widget child})
|
||||
: super(key: key, child: child);
|
||||
|
||||
@override
|
||||
bool updateShouldNotify(covariant InfoInheritedWidget oldWidget) =>
|
||||
info != oldWidget.info;
|
||||
|
||||
static InfoInheritedWidget of(BuildContext context) =>
|
||||
context.dependOnInheritedWidgetOfExactType<InfoInheritedWidget>();
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020-04-01
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明: 227 AnimatedModalBarrier 动画屏障模
|
||||
/// 内部依赖 ModalBarrier 实现,功能一致,只不过该组件可以传入一个颜色动画,进行过渡展现。
|
||||
/// link: 212
|
||||
// {
|
||||
// "widgetId": 227,
|
||||
// "name": 'AnimatedModalBarrier 介绍',
|
||||
// "priority": 1,
|
||||
// "subtitle":
|
||||
// "【dismissible】 : 点击是否返回 【bool】\n"
|
||||
// "【color】 : 颜色 【Animation<Color>】",
|
||||
// }
|
||||
class AnimatedModalBarrierDemo extends StatefulWidget {
|
||||
@override
|
||||
_AnimatedModalBarrierDemoState createState() => _AnimatedModalBarrierDemoState();
|
||||
}
|
||||
|
||||
class _AnimatedModalBarrierDemoState extends State<AnimatedModalBarrierDemo>
|
||||
with SingleTickerProviderStateMixin {
|
||||
AnimationController _controller;
|
||||
Animation<Color> _color;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller =
|
||||
AnimationController(vsync: this, duration: Duration(seconds: 2))..forward();
|
||||
_color = ColorTween(begin: Colors.blue, end: Colors.purple)
|
||||
.animate(_controller);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: 200,
|
||||
height: 100,
|
||||
child: Stack(alignment: Alignment.center, children: [
|
||||
AnimatedModalBarrier(
|
||||
dismissible: true,
|
||||
color: _color,
|
||||
),
|
||||
Text('点击背景返回',style: TextStyle(color: Colors.white),)
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020/9/21
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明: 223 DropdownButtonFormField 表单下拉框
|
||||
/// 底层依赖 DropdownButton 实现,所以基本属性类似。但拥有 FormField 的特性,可以回调 onSaved、validator 方法。
|
||||
/// link: 55,222
|
||||
///
|
||||
// {
|
||||
// "widgetId": 223,
|
||||
// "name": '表单下拉框简单使用',
|
||||
// "priority": 1,
|
||||
// "subtitle":
|
||||
// "【items】 : 子组件列表 【List<DropdownMenuItem<T>>】\n"
|
||||
// "【validator】 : 表单验证回调 【FormFieldValidator<T>】\n"
|
||||
// "【onSaved】 : 表单保存回调 【FormFieldSetter<T>】\n"
|
||||
// "其他属性详见 DropdownButton,表单校验特性详见 FormField。",
|
||||
// }
|
||||
|
||||
class DropdownButtonFormFieldDemo extends StatefulWidget {
|
||||
@override
|
||||
_DropdownButtonFormFieldDemoState createState() => _DropdownButtonFormFieldDemoState();
|
||||
}
|
||||
|
||||
class _DropdownButtonFormFieldDemoState extends State<DropdownButtonFormFieldDemo> {
|
||||
Color _color;
|
||||
final _colors = [Colors.red, Colors.yellow, Colors.blue, Colors.green];
|
||||
final _info = ["红色", "黄色", "蓝色", "绿色"];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Wrap(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 20),
|
||||
width: 50,
|
||||
height: 50,
|
||||
color: _color??_colors[0],
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
width: 80,
|
||||
child: DropdownButtonFormField<Color>(
|
||||
value: _color,
|
||||
elevation: 1,
|
||||
hint: Text('选择颜色',style: TextStyle(fontSize: 12),),
|
||||
icon: Icon(
|
||||
Icons.expand_more,
|
||||
size: 20,
|
||||
color: _color,
|
||||
),
|
||||
items: _buildItems(),
|
||||
onChanged: (v) => setState(() => _color = v)
|
||||
),
|
||||
)
|
||||
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
List<DropdownMenuItem<Color>> _buildItems() => _colors
|
||||
.map((e) => DropdownMenuItem<Color>(
|
||||
value: e,
|
||||
child: Text(
|
||||
_info[_colors.indexOf(e)],
|
||||
style: TextStyle(color: e),
|
||||
)))
|
||||
.toList();
|
||||
}
|
||||
36
lib/views/widgets/StatefulWidget/FormField/node1_base.dart
Normal file
36
lib/views/widgets/StatefulWidget/FormField/node1_base.dart
Normal file
@@ -0,0 +1,36 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020-04-01
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明: 222 FormField 表单字段
|
||||
/// 一个表单字段,需要在 Form 组件中使用,内含泛型 T 的字段作为状态量,对根据字段的更新和验证会触发相应回调。
|
||||
/// link:198,199,223,
|
||||
// {
|
||||
// "widgetId": 222,
|
||||
// "name": 'FormField 介绍',
|
||||
// "priority": 1,
|
||||
// "subtitle":
|
||||
// "【builder】 : 内容构造器 【FormFieldBuilder<T>】\n"
|
||||
// "【initialValue】 : 初始值 【T】\n"
|
||||
// "【validator】 : 验证函数 【FormFieldValidator<String> 】\n"
|
||||
// "【enabled】 : 是否有效 【bool】\n"
|
||||
// "【onSaved】 : 表单save时回调 【FormFieldSetter<String>】",
|
||||
// }
|
||||
class FormFieldDemo extends StatelessWidget {
|
||||
final String info =
|
||||
'FormField 代表表单中的一个字段,对于字符串类型的字段,框架中封装了 TextFormField 以便使用;下拉选择的字段,用 DropdownButtonFormField。'
|
||||
'目前框架中 FormField 的子类也只有这两个。既然是表单字段,必然是要和 Form 组件一起使用。通过对 Form 添加 GlobalKey ,来获取 FormState 对象。'
|
||||
'当 FormState 调用 save 方法时,所有的 FormField 都会触发 onSave 方法,当 FormState 调用 validate 方法时,所有的 FormField 都会触发 validate 方法。';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
|
||||
return Container(
|
||||
color: Colors.blue.withOpacity(0.1),
|
||||
padding: EdgeInsets.all(10),
|
||||
margin: EdgeInsets.all(10),
|
||||
child: Text(info),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020-04-01
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明: 235 PaginatedDataTable 可分页表格
|
||||
/// 一个功能丰富的可分页表格组件,可指定分页数、排列、页码前后切换。
|
||||
/// link: 110,102
|
||||
// {
|
||||
// "widgetId": 235 ,
|
||||
// "name": 'PaginatedDataTable 使用',
|
||||
// "priority": 1,
|
||||
// "subtitle":
|
||||
// "【header】 : 表名 【Widget】\n"
|
||||
// "【rowsPerPage】 : 每页记录数 【int】\n"
|
||||
// "【actions】 : 操作组件 【List<Widget>】\n"
|
||||
// "【columns】 : 数据列 【List<DataColumn>】\n"
|
||||
// "【sortColumnIndex】 : 排序列索引 【int】\n"
|
||||
// "【sortAscending】 : 是否升序 【bool】\n"
|
||||
// "【onSelectAll】 : 全选回调 【ValueSetter<bool>】\n"
|
||||
// "【onRowsPerPageChanged】 : 分页改变监听 【ValueChanged<int>】\n"
|
||||
// "【availableRowsPerPage】 : 可用分页列表 【List<int>】\n"
|
||||
// "【source】 : 数据源 【DataTableSource】",
|
||||
// }
|
||||
class PaginatedDataTableDemo extends StatefulWidget {
|
||||
@override
|
||||
State<StatefulWidget> createState() => _PaginatedDataTableDemoState();
|
||||
}
|
||||
|
||||
class _PaginatedDataTableDemoState extends State<PaginatedDataTableDemo> {
|
||||
int _rowsPerPage = 5;
|
||||
|
||||
int _sortColumnIndex;
|
||||
bool _sortAscending = true;
|
||||
|
||||
final DessertDataSource _dessertsDataSource = DessertDataSource();
|
||||
|
||||
void sort<T>(
|
||||
Comparable<T> getField(HeroInfo d), int columnIndex, bool ascending) {
|
||||
_dessertsDataSource.sort<T>(getField, ascending);
|
||||
setState(() {
|
||||
_sortColumnIndex = columnIndex;
|
||||
_sortAscending = ascending;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
height: 300,
|
||||
width: 350,
|
||||
child: SingleChildScrollView(
|
||||
child: PaginatedDataTable(
|
||||
actions: <Widget>[
|
||||
IconButton(icon: Icon(Icons.add), onPressed: null),
|
||||
],
|
||||
header: const Text(
|
||||
'《旷古奇书》-角色预设',
|
||||
style: TextStyle(color: Colors.blue),
|
||||
),
|
||||
rowsPerPage: _rowsPerPage,
|
||||
availableRowsPerPage: [5, 8, 10, 15],
|
||||
onRowsPerPageChanged: (int value) {
|
||||
setState(() {
|
||||
_rowsPerPage = value;
|
||||
});
|
||||
},
|
||||
sortColumnIndex: _sortColumnIndex,
|
||||
sortAscending: _sortAscending,
|
||||
onSelectAll: _dessertsDataSource._selectAll,
|
||||
columns: <DataColumn>[
|
||||
DataColumn(
|
||||
label: const Text('角色名称'),
|
||||
onSort: (int columnIndex, bool ascending) => sort<String>(
|
||||
(HeroInfo d) => d.name, columnIndex, ascending)),
|
||||
DataColumn(
|
||||
label: const Text('主场卷部'),
|
||||
tooltip: '人物主要出场的作品.',
|
||||
numeric: true,
|
||||
onSort: (int columnIndex, bool ascending) => sort<String>(
|
||||
(HeroInfo d) => d.calories, columnIndex, ascending)),
|
||||
DataColumn(
|
||||
label: const Text('种族'),
|
||||
numeric: true,
|
||||
onSort: (int columnIndex, bool ascending) => sort<String>(
|
||||
(HeroInfo d) => d.fat, columnIndex, ascending)),
|
||||
DataColumn(
|
||||
label: const Text('性别'),
|
||||
numeric: true,
|
||||
onSort: (int columnIndex, bool ascending) => sort<String>(
|
||||
(HeroInfo d) => d.carbs, columnIndex, ascending)),
|
||||
],
|
||||
source: _dessertsDataSource),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class HeroInfo {
|
||||
HeroInfo(this.name, this.calories, this.fat, this.carbs);
|
||||
|
||||
final String name;
|
||||
final String calories;
|
||||
final String fat;
|
||||
final String carbs;
|
||||
bool selected = false;
|
||||
}
|
||||
|
||||
class DessertDataSource extends DataTableSource {
|
||||
final List<HeroInfo> _desserts = <HeroInfo>[
|
||||
HeroInfo('捷特', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('龙少', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('巫缨', '《幻将录》', "人族", "女"),
|
||||
HeroInfo('林兮', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('九方玄玉', '《风神传》', "神族", "男"),
|
||||
HeroInfo('七日洪荒', '《风神传》', "魔族", "男"),
|
||||
HeroInfo('林昔瑶', '《封妖志》', "鬼族", "女"),
|
||||
HeroInfo('林兮鬼帝', '《封妖志》', "鬼族", "男"),
|
||||
HeroInfo('艾隆', '《封妖志》', "鬼族", "男"),
|
||||
HeroInfo('语熙华', '《风神传》', "道族", "男"),
|
||||
HeroInfo('雪玉宛如', '《幻将录》', "人族", "女"),
|
||||
HeroInfo('破千', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('浪封', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('虎翼穷奇', '《封妖志》', "妖族", "男"),
|
||||
HeroInfo('凯', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('荆棘', '《幻将录》', "人族", "女"),
|
||||
HeroInfo('龙右', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('梦千', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('梦小梦', '《幻将录》', "人族", "女"),
|
||||
HeroInfo('梦瞳', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('十戈', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('计画天', '《幻将录》', "人族", "女"),
|
||||
HeroInfo('士方', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('巫妻孋', '《幻将录》', "人族", "女"),
|
||||
HeroInfo('木时黎', '《永恒传说》', "人族", "男"),
|
||||
HeroInfo('木艾奇', '《永恒传说》', "人族", "男"),
|
||||
HeroInfo('张风', '《永恒传说》', "人族", "男"),
|
||||
HeroInfo('薛剑儿', '《永恒传说》', "人族", "男"),
|
||||
HeroInfo('李月', '《永恒传说》', "人族", "女"),
|
||||
HeroInfo('刘雪', '《永恒传说》', "人族", "女"),
|
||||
HeroInfo('葛心', '《永恒传说》', "人族", "女"),
|
||||
HeroInfo('步映容', '《幻将录》', "人族", "女"),
|
||||
HeroInfo('莫慈良', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('莫向阳', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('莫子薇', '《永恒传说》', "人族", "女"),
|
||||
HeroInfo('藏凯阳', '《永恒传说》', "人族", "男"),
|
||||
HeroInfo('奇雨歆', '《永恒传说》', "人族", "女"),
|
||||
HeroInfo('林天蕊', '《永恒传说》', "人族", "女"),
|
||||
HeroInfo('吴灏然', '《永恒传说》', "人族", "男"),
|
||||
HeroInfo('何解连', '《永恒传说》', "人族", "男"),
|
||||
HeroInfo('步络尘', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('拓雷', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('炽阳骑', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('正构', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('烈', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('梦华君', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('初星', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('梦飞烟', '《幻将录》', "人族", "男"),
|
||||
HeroInfo('武落英', '《幻将录》', "人族", "女"),
|
||||
HeroInfo('古千缘', '《幻将录》', "人族", "男"),
|
||||
];
|
||||
|
||||
void sort<T>(Comparable<T> getField(HeroInfo d), bool ascending) {
|
||||
_desserts.sort((HeroInfo a, HeroInfo b) {
|
||||
if (!ascending) {
|
||||
final HeroInfo c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
final Comparable<T> aValue = getField(a);
|
||||
final Comparable<T> bValue = getField(b);
|
||||
return Comparable.compare(aValue, bValue);
|
||||
});
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
int _selectedCount = 0;
|
||||
|
||||
@override
|
||||
DataRow getRow(int index) {
|
||||
if (index >= _desserts.length) return null;
|
||||
final HeroInfo dessert = _desserts[index];
|
||||
return DataRow.byIndex(
|
||||
index: index,
|
||||
selected: dessert.selected,
|
||||
onSelectChanged: (bool value) {
|
||||
if (dessert.selected != value) {
|
||||
_selectedCount += value ? 1 : -1;
|
||||
assert(_selectedCount >= 0);
|
||||
dessert.selected = value;
|
||||
notifyListeners();
|
||||
}
|
||||
},
|
||||
cells: <DataCell>[
|
||||
DataCell(Center(child: Text('${dessert.name}'))),
|
||||
DataCell(Center(child: Text('${dessert.calories}'))),
|
||||
DataCell(Center(child: Text('${dessert.fat}'))),
|
||||
DataCell(Center(child: Text('${dessert.carbs}'))),
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get isRowCountApproximate => false;
|
||||
|
||||
@override
|
||||
int get rowCount => _desserts.length;
|
||||
|
||||
@override
|
||||
int get selectedRowCount => _selectedCount;
|
||||
|
||||
void _selectAll(bool checked) {
|
||||
for (HeroInfo dessert in _desserts) dessert.selected = checked;
|
||||
_selectedCount = checked ? _desserts.length : 0;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
@@ -23,37 +23,23 @@ class _CustomTextFormFieldState extends State<CustomTextFormField> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child:
|
||||
Stack(
|
||||
alignment: Alignment.centerRight,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
width: 350,
|
||||
child: UnconstrainedBox(
|
||||
child: Container(
|
||||
width: 200,
|
||||
height: 70,
|
||||
child: TextFormField(
|
||||
style: TextStyle(textBaseline: TextBaseline.alphabetic),
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'username',
|
||||
),
|
||||
validator: _validateUsername,
|
||||
onFieldSubmitted: _onFieldSubmitted,
|
||||
onSaved: _onSaved,
|
||||
),
|
||||
),
|
||||
),
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
SizedBox(width: 40),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
style: TextStyle(textBaseline: TextBaseline.alphabetic),
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
labelText: 'username',
|
||||
),
|
||||
Positioned(
|
||||
top: 0, right: 0, child: _buildSubmitButton(context)),
|
||||
],
|
||||
validator: _validateUsername,
|
||||
onFieldSubmitted: _onFieldSubmitted,
|
||||
onSaved: _onSaved,
|
||||
),
|
||||
),
|
||||
),
|
||||
_buildSubmitButton(context),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// create by 张风捷特烈 on 2020-04-01
|
||||
/// contact me by email 1981462002@qq.com
|
||||
/// 说明: 212 ModalBarrier 屏障模
|
||||
/// 相当于一块幕布,防止用户与其背后的 Widget 交互,可以通过 dismissible 决定点击时,是否触发返回栈。源码中用于 Dialog 相关组件。
|
||||
/// link: 227,126,127,128
|
||||
// {
|
||||
// "widgetId": 212,
|
||||
// "name": 'ModalBarrier 介绍',
|
||||
// "priority": 1,
|
||||
// "subtitle":
|
||||
// "【dismissible】 : 点击是否返回 【bool】\n"
|
||||
// "【color】 : 颜色 【Color】",
|
||||
// }
|
||||
class ModalBarrierDemo extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: 200,
|
||||
height: 100,
|
||||
child: Stack(alignment: Alignment.center, children: [
|
||||
ModalBarrier(
|
||||
dismissible: true,
|
||||
color: Colors.grey.withOpacity(0.3),
|
||||
),
|
||||
Text('点击背景返回')
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -30,3 +30,5 @@ export '../ProxyWidget/TableCell/node1_base.dart';
|
||||
export '../ProxyWidget/KeepAlive/node1_base.dart';
|
||||
export '../ProxyWidget/CupertinoUserInterfaceLevel/node1_base.dart';
|
||||
export '../ProxyWidget/InheritedTheme/node1_base.dart';
|
||||
export '../ProxyWidget/DefaultAssetBundle/node1_base.dart';
|
||||
export '../ProxyWidget/InheritedWidget/node1_base.dart';
|
||||
|
||||
@@ -78,8 +78,11 @@ export '../StatefulWidget/RawGestureDetector/node1_base.dart';
|
||||
|
||||
export '../StatefulWidget/Dismissible/node1_base.dart';
|
||||
export '../StatefulWidget/AutomaticKeepAlive/node1_base.dart';
|
||||
export '../StatefulWidget/AnimatedModalBarrier/node1_base.dart';
|
||||
export '../StatefulWidget/FormField/node1_base.dart';
|
||||
export '../StatefulWidget/AnimatedBuilder/node1_base.dart';
|
||||
export '../StatefulWidget/TweenAnimationBuilder/node1_base.dart';
|
||||
export '../StatefulWidget/PaginatedDataTable/node1_base.dart';
|
||||
export '../StatefulWidget/RawKeyboardListener/node1_base.dart';
|
||||
export '../StatefulWidget/Dismissible/node2_direction.dart';
|
||||
|
||||
@@ -100,6 +103,7 @@ export '../StatefulWidget/AnimatedPositioned/node1_base.dart';
|
||||
export '../StatefulWidget/AnimatedPositionedDirectional/node1_base.dart';
|
||||
|
||||
export '../StatefulWidget/ExpansionPanelList/node1_base.dart';
|
||||
export '../StatefulWidget/DropdownButtonFormField/node1_base.dart';
|
||||
|
||||
export '../StatefulWidget/Ink/node1_base.dart';
|
||||
export '../StatefulWidget/Ink/node2_image.dart';
|
||||
|
||||
@@ -50,6 +50,7 @@ export '../StatelessWidget/Divider/node1_base.dart';
|
||||
export '../StatelessWidget/Divider/node2_height.dart';
|
||||
|
||||
export '../StatelessWidget/ScrollView/node1_base.dart';
|
||||
export '../StatelessWidget/ModalBarrier/node1_base.dart';
|
||||
export '../StatelessWidget/BoxScrollView/node1_base.dart';
|
||||
export '../StatelessWidget/FloatingActionButton/node1_base.dart';
|
||||
export '../StatelessWidget/FloatingActionButton/node2_mini.dart';
|
||||
|
||||
@@ -83,6 +83,34 @@ class WidgetsMap {
|
||||
return [
|
||||
InheritedThemeDemo(),
|
||||
];
|
||||
case "ModalBarrier":
|
||||
return [
|
||||
ModalBarrierDemo(),
|
||||
];
|
||||
case "AnimatedModalBarrier":
|
||||
return [
|
||||
AnimatedModalBarrierDemo(),
|
||||
];
|
||||
case "DefaultAssetBundle":
|
||||
return [
|
||||
DefaultAssetBundleDemo(),
|
||||
];
|
||||
case "DropdownButtonFormField":
|
||||
return [
|
||||
DropdownButtonFormFieldDemo(),
|
||||
];
|
||||
case "FormField":
|
||||
return [
|
||||
FormFieldDemo(),
|
||||
];
|
||||
case "PaginatedDataTable":
|
||||
return [
|
||||
PaginatedDataTableDemo(),
|
||||
];
|
||||
case "InheritedWidget":
|
||||
return [
|
||||
InheritedWidgetDemo(),
|
||||
];
|
||||
case "ScrollView":
|
||||
return [
|
||||
ScrollViewDemo(),
|
||||
|
||||
Reference in New Issue
Block a user