从一开始接触Flutter,相信读者都会铭记一句话,那就是——一切皆组件。今天我们就来体会一下这句话的神奇魔力,我们先从实际的产品需求说起。

我们先来看一个简化的运行图:

我们要实现如上图所示的日期选择器,App是iOS风格。

Flutter SDK自身有类似上图的日期选择器,但是Material Design的,于是我到Flutter库中找到了一个名为flutter_date_pickers的三方库,版本为0.1.4(https://pub.flutter-io.cn/packages/flutter_date_pickers)。

接下来就是集成这个库了,具体代码按照文档直接复制:

@override
Widget build(BuildContext context) {
DatePickerRangeStyles styles = DatePickerRangeStyles(
selectedPeriodLastDecoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.only(
topRight: Radius.circular(10.0),
bottomRight: Radius.circular(10.0))),
selectedPeriodStartDecoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0), bottomLeft: Radius.circular(10.0)),
),
selectedPeriodMiddleDecoration:
BoxDecoration(color: Colors.yellow, shape: BoxShape.rectangle),
);
return CupertinoPageScaffold(
child: WeekPicker(
selectedDate: DateTime.now(),
onChanged: (dateRange) {},
firstDate: DateTime.now().subtract(Duration(days: 10)),
lastDate: DateTime.now().add(Duration(minutes: 10)),
datePickerStyles: styles)
);
}

本来以为可以正常运行的,结果整个App崩溃了。报错堆栈信息如下:

The following NoSuchMethodError was thrown building WeekPicker(dirty, dependencies: [_LocalizationsScope-[GlobalKey#678bc]]):

The getter 'firstDayOfWeekIndex' was called on null.

Receiver: null

Tried calling: firstDayOfWeekIndex

接着,根据堆栈信息找到代码出错位置,发现是这个库中week_picker.dart文件中出现问题,下面的代码是问题所在:

MaterialLocalizations localizations = MaterialLocalizations.of(context);

ISelectablePicker<DatePeriod> weekSelectablePicker = WeekSelectable(
selectedDate,
datePickerStyles.firstDayOfeWeekIndex ?? localizations.firstDayOfWeekIndex,
firstDate,
lastDate,
selectableDayPredicate: selectableDayPredicate
);

很明显,这里使用了MaterialLocalizations对象localizations,而MaterialLocalizations.of(context);方法返回了null,所以在接下来的代码中抛出了空指针异常。

解决的方法很简单,只要修改源码,如果通过MaterialLocalizations来初始化localizations得到null,那么就通过CupertinoLocalizations来初始化它就行了。具体代码如下:

CupertinoLocalizations localizations = CupertinoLocalizations.of(context);

在接下来的使用时,替换为:

localizations.datePickerDateOrder.index

即可。

但是,这毕竟需要改第三方库的源代码,有没有办法不改源码呢?答案是肯定的。

我们一开始就提到一切皆组件的概念,那么,有没有可能App依然使用iOS风格,然后把MaterialApp嵌套到CupertinoPageScaffold中呢?换一种说法,我们可不可以把MaterialApp和与之相关的Scaffold当做普通的组件,被CupertinoPageScaffold所包含呢?来看下面的代码:

@override
Widget build(BuildContext context) {
DatePickerRangeStyles styles = DatePickerRangeStyles(
selectedPeriodLastDecoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.only(
topRight: Radius.circular(10.0),
bottomRight: Radius.circular(10.0))),
selectedPeriodStartDecoration: BoxDecoration(
color: Colors.green,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10.0), bottomLeft: Radius.circular(10.0)),
),
selectedPeriodMiddleDecoration:
BoxDecoration(color: Colors.yellow, shape: BoxShape.rectangle),
);
return CupertinoPageScaffold(
child: MaterialApp(
home: Scaffold(
appBar: CupertinoNavigationBar(middle: Text('Incredible Flutter')),
body: WeekPicker(
selectedDate: DateTime.now(),
onChanged: (dateRange) {},
firstDate: DateTime.now().subtract(Duration(days: 10)),
lastDate: DateTime.now().add(Duration(minutes: 10)),
datePickerStyles: styles))));
}

仔细阅读上述代码,可见:我们只是在return语句中增加了MaterialApp和Scaffold组件,重新运行程序,结果可以正常运行了。

另外还要注意,Scaffold中的appBar,我们经常给定的是AppBar对象,但为了实现iOS的界面风格,我们将其值改为CupertinoNavigationBar,也是没有问题的。

好了,本次分享到此结束,希望上述内容能够帮到你。

一切皆组件的Flutter,安能辨我是雄雌的更多相关文章

  1. python金牌班第七周周末总结

    python金牌班第七周周末总结 面向对象前戏 1.我们在学习面相对像之前有一个推导过程如何将我们之前写的东西,从一串代码转向给对象服务. 2.实例 我们首先模拟了两个物种进行战斗的场景,然后我们发现 ...

  2. 理清C++常量指针和指针常量这团乱麻

    写在前面: 与其说C++中的常量指针和指针常量是一块很有嚼头的语法糖,不如说它是一块相当难啃的骨头.其实本来没什么,这无非是const int *p与int* const p的区别, 但一涉及到起名字 ...

  3. Java开发笔记(五十二)对象的类型检查

    前面介绍了类的多态性,来自于鸡类的实例chicken,既能用来表达公鸡实例,也能用来表达母鸡实例.可是这导致了一个问题,假如在call方法内部需要手工判断输入参数属于公鸡实例还是母鸡实例,那该如何是好 ...

  4. Flutter 中那么多组件,难道要都学一遍?

    在 Flutter 中一切皆是 组件,仅仅 Widget 的子类和间接子类就有 350 多个,整理的 Flutter组件继承关系图 可以帮助大家更好的理解学习 Flutter,回归正题,如此多的组件到 ...

  5. 【老孟Flutter】Stateful 组件的生命周期​

    老孟导读:关于生命周期的文章共有2篇,第一篇是介绍 Flutter 中Stateful 组件的生命周期. 博客地址:http://laomengit.com/blog/20201227/Statefu ...

  6. Flutter 目录结构介绍、入口、自定义 Widget、MaterialApp 组件、Scaffold 组件

    Flutter 目录结构介绍 文件夹 作用 android android 平台相关代码 ios ios 平台相关代码 lib flutter 相关代码,我们主要编写的代 码就在这个文件夹 test ...

  7. flutter Container组件和Text组件

    在开始之前,我们先写一个最简单的入口文件:     后面,都是在这个结构的基础上面完成的. 由于Container组件和Text组件都是写在body里面的,所以下面,先将body抽离成一个组件的形式. ...

  8. 【Flutter学习】组件学习之目录

    01. Flutter组件-Layout-Container-容器  02. Flutter组件-Text-Text-文本  03. Flutter组件-Text-RichText-富文本  04. ...

  9. Flutter 中的常见的按钮组件 以及自 定义按钮组件

    一.Flutter 中的按钮组件介绍   Flutter 里有很多的 Button 组件很多,常见的按钮组件有:RaisedButton.FlatButton.   IconButton.Outlin ...

随机推荐

  1. Redis系列(八):发布与订阅

    Redis的发布与订阅,有点类似于消息队列,发送者往频道发送消息,频道的订阅者接收消息. 1. 发布与订阅示例 首先,在本机开启第1个Redis客户端,执行如下命令订阅blog.redis频道: SU ...

  2. JAVA设计模式 4【创建型】理解建造者模式

    Hello,又是拖了几天更,实在是忙的要死,有时候忙累了,真的就是倒头睡的那种,刚好今天闲下来了.今天来更新一篇建造者模式. 其实建造者模式,我们已经在上一节已经有了解过了.只不过是上一节没有提到这样 ...

  3. Redis系列(十):数据结构Set源码解析和SADD、SINTER、SDIFF、SUNION、SPOP命令

    1.介绍 Hash是以K->V形式存储,而Set则是K存储,空间节省了很多 Redis中Set是String类型的无序集合:集合成员是唯一的. 这就意味着集合中不能出现重复的数据.可根据应用场景 ...

  4. 【搬砖】/etc/passwd 文件结构

    文件的内容: 每个Linux都会有root账号,以此来说明,从内容上看,每行都使用[:]分隔(注意:每行前面的数字是行号,不是内容),所以一共有七部分内容,分别是: 1. 账号名称:root,用来对应 ...

  5. 5000+字硬核干货!Redis 分布式集群部署实战

    原理: Redis集群采用一致性哈希槽的方式将集群中每个主节点都分配一定的哈希槽,对写入的数据进行哈希后分配到某个主节点进行存储. 集群使用公式(CRC16 key)& 16384计算键key ...

  6. springSecurity使用

    目录 1.1 依赖包导入 2.1 没有安全机制下的一个web 3.1 做一个安全机制的web 官网https://spring.io/guides/gs/securing-web/ 无情的翻译官... ...

  7. python 检索文件内容工具

    公司内部需求一个工具检索目录下的文件在另外的目录中使用次数, 用来优化包体的大小. 此代码效率并不高效, 另添加对应的 后缀检索. 用python 实现比较快速, 另还有缺点是只支持 utf-8 格式 ...

  8. drf路由与认证

    目录 一.路由 1 没有继承视图集的视图类 2 继承了视图集的视图类 3 继承自ModelViewSet的路由写法(自动生成) 二.认证 1 drf认证的源码分析 2 自定义认证类的使用 一.路由 三 ...

  9. python-----内存管理机制

    一.深浅拷贝的区别 深浅拷贝一般是在列表嵌套列表的情况下去讨论 浅拷贝:只拷贝列表中对象的引用,嵌套列表中的数据是不会进行全部拷贝的 深拷贝:会把对象里面所有的数据都拷贝一份,不再只拷贝对象的引用,会 ...

  10. 机器学习实战基础(二十六):sklearn中的降维算法PCA和SVD(七) 附录