从一开始接触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. sql 语句和实例

    修改字段格式的sql语句: alter table tablename alter column colname newDataType 比如:alter table mytable alter co ...

  2. jquery ajax 参数列表定义

    出处:http://www.cnblogs.com/tylerdonet/ 1.url         (要求为String类型的参数,(默认为当前页地址)发送请求的地址) 2.type       ...

  3. 教你如何开发一个完败Miracast的投屏新功能

      手机与电视,是陪伴在我们生活最常见,陪伴最长久的智能设备.迅猛发展的移动终端与通信技术,赋予了手机更广阔多元的应用生态,大屏电视则以大视野和震撼影音,弥补了手里方寸带来的视觉局限.而今,手机的延伸 ...

  4. POJ 3263 Tallest Cow 题解

    题目 FJ's \(N (1 ≤ N ≤ 10,000)\) cows conveniently indexed 1..N are standing in a line. Each cow has a ...

  5. SpringBoot系列之前后端接口安全技术JWT

    @ 目录 1. 什么是JWT? 2. JWT令牌结构怎么样? 2.1 标头(Header) 2.2 有效载荷(Playload) 2.3 签名(Signature) 3. JWT原理简单介绍 4. J ...

  6. python面试题五:Python 编程

    1.B Tree和B+ Tree的区别? 1.B树中同一键值不会出现多次,并且有可能出现在叶结点,也有可能出现在非叶结点中. 而B+树的键一定会出现在叶结点中,并有可能在非叶结点中重复出现,以维持B+ ...

  7. 数据可视化之powerBI技巧(十三)PowerBI作图技巧:动态坐标轴

    之前的文章中介绍了如何制作动态的分析指标,这篇进行文章再介绍一下如何制作动态的坐标轴. 假设要分析的数据为销售额,分别从产品和地区两个维度进行分析,要实现的效果是,如果选择的是产品,则坐标轴是各个产品 ...

  8. python 装饰器(五):装饰器实例(二)类装饰器(类装饰器装饰函数)

    回到装饰器上的概念上来,装饰器要求接受一个callable对象,并返回一个callable对象(不太严谨,详见后文). 那么用类来实现也是也可以的.我们可以让类的构造函数__init__()接受一个函 ...

  9. 数据可视化之PowerQuery篇(九)巧用Power Query,Excel也可以轻松管理文档

    https://zhuanlan.zhihu.com/p/111674088 ​来自知乎一个朋友的问题,如何在Excel中批量插入文件的超链接,以便在Excel中对文档进行有序的目录管理? 这个问题的 ...

  10. HangFire多集群切换及DashBoard登录验证

    项目中是有多个集群的,现在存在一个是:在切换web集群时,如何切换HangFire的周期性任务. 先采取的解决办法是: 每个集群分一个队列,在周期性任务入队时分配当前web集群的集群id单做队列名称. ...