关于Flutter的那些事儿
作者:坚果
公众号:""
华为云享专家,InfoQ签约作者,阿里云专家博主,51CTO博客首席体验官,,专注于大前端技术的分享,包括Flutter,小程序,安卓,VUE,JavaScript。
深入理解 Flutter 布局约束 首先,
上层 widget 向下层 widget 传递约束条件;
然后,下层 widget 向上层 widget 传递大小信息。
最后,上层 widget 决定下层 widget 的位置。
更多细节:
-
Widget 会通过它的 父级 获得自身的约束。约束实际上就是 4 个浮点类型的集合:最大/最小宽度,以及最大/最小高度。
-
然后,这个 widget 将会逐个遍历它的 children 列表。向子级传递 约束(子级之间的约束可能会有所不同),然后询问它的每一个子级需要用于布局的大小。
-
然后,这个 widget 就会对它子级的 children 逐个进行布局。(水平方向是
x
轴,竖直是y
轴) -
了解如何为特定 widget 制定布局规则
掌握通用布局是非常重要的,但这还不够。
应用一般规则时,每个 widget 都具有很大的自由度,所以没有办法只看 widget 的名称就知道可能它长什么样。
如果你尝试推测,可能就会猜错。除非你已阅读 widget 的文档或研究了其源代码,否则你无法确切知道 widget 的行为。
布局源代码通常很复杂,因此阅读文档是更好的选择。但是当你在研究布局源代码时,可以使用 IDE 的导航功能轻松找到它。
下面是一个例子:
-
在你的代码中找到一个
Column
并跟进到它的源代码。为此,请在 (Android Studio/IntelliJ) 中使用command+B
(macOS)或control+B
(Windows/Linux)。你将跳到basic.dart
文件中。由于Column
扩展了Flex
,请导航至Flex
源代码(也位于basic.dart
中)。 -
向下滚动直到找到一个名为
createRenderObject()
的方法。如你所见,此方法返回一个RenderFlex
。它是Column
的渲染对象,现在导航到flex.dart
文件中的RenderFlex
的源代码。 -
向下滚动,直到找到
performLayout()
方法,由该方法执行列布局。
状态管理
-
Widget 管理自己的状态。
-
Widget 管理子 Widget 状态。
-
混合管理(父 Widget 和子 Widget 都管理状态)
什么是Flutter?
Flutter是一个开放源码的UI 由谷歌创建的开发套件。它用于从单个代码库开发适用于 Android、iOS、Linux、Mac、Windows 和 Web 的应用程序。Flutter 应用程序是用 Dart 语言编写的。
什么是Dart?
Dart 是一种客户端优化的编程语言,适用于多个平台上的应用程序。它由 Google 开发,用于构建移动、桌面、服务器和 Web 应用程序。Dart 是一种面向对象、基于类、垃圾收集的语言,具有 C 风格的语法。Dart 可以编译为原生代码或 JavaScript。
有状态和无状态widget有什么区别?
-
无状态widget不需要可变状态,即它是不可变的。无状态widget的状态只创建一次——因此,构建方法也只调用一次。简而言之,无状态widget在应用程序运行期间无法更改其状态,这意味着在应用程序运行时无法重绘widget。如果要重绘无状态widget,则需要创建widget的新实例。
-
有状态widget具有可变状态,即它们是可变的并且可以在其生命周期内多次绘制。它们是可以多次更改状态的widget,并且可以在应用程序运行时在屏幕上多次重绘。
State 是什么意思?什么是 setState()?
状态是widget的变量值/属性的集合。任何可以改变的东西,比如计数器计数、文本等,都可以成为 State 的一部分。
setState() 本质上是一种告诉应用程序使用新值/属性刷新和重建屏幕的方法。
状态对象由框架创建。为了更改您的widget,您需要更新状态对象,这可以使用可用于有状态widget的 setState() 函数来完成。setState() 设置状态对象的属性,进而触发 UI 的更新。但是这种技术有其自身的缺点。
“StatefulWidget”的生命周期是什么?
-
createState()
— a 中的一个方法会StatefulWidget
立即被调用,并且应该State
为widget返回一个对象 -
initState()
—State
创建widget后在对象中调用的第一个方法 -
didChangeDependencies()
—initState()
在第一次构建widget后立即调用 -
build()
— 与StatelessWidget
. 它在 之后立即调用didChangeDependencies()
。每次 UI 需要渲染并返回widget的树时都会调用它。 -
didUpdateWidget()
— 当父widget发生变化并需要重绘其 UI 时调用它 -
deactivate()
— 调用 beforedispose()
,当这个对象从树中移除时 -
dispose()
— 在释放整个widget及其状态时调用。
热重载、热重启和完全重启有什么区别?
Flutter 的热重载功能可帮助您快速轻松地进行实验、构建 UI、添加功能和修复错误。热重载的工作原理是将更新的源代码文件注入正在运行的 Dart 虚拟机 (VM)。VM 用新版本的字段和函数更新类后,Flutter 框架会自动重建widget树,让您可以快速查看更改的效果。
-
热重载将代码更改加载到 VM 中并重新构建widget树,保留应用程序状态;它不会重新运行 main() 或 initState()。热重载比热重启花费的时间更少。
-
热重启将代码更改加载到 VM 中,并重新启动 Flutter 应用程序,从而丢失应用程序状态。热重启比热重载花费的时间长得多。
-
完全重新启动会重新启动 iOS、Android 或 Web 应用程序。这需要更长的时间,因为它还会重新编译 Java/Kotlin/ObjC/Swift 代码。在 Web 上,它还会重新启动 Dart 开发编译器。
Flutter的优点
-
跨平台开发
-
更快的开发
-
好社区
-
实时和热重载
-
原生性能
-
提供原生的外观和感觉
SliverList的使用
在此之前先来了解一下CustomScrollView,
CustomScrollView
是Flutter
提供的可以用来自定义滚动效果的组件,它可以像胶水一样将多个Sliver
粘合在一起。
假如页面中同时存在一个List
和一个Grid
,虽然它们看起来是一个整体,但是由于各自的滚动效果是分离的,所以没法保证一致的滚动效果。
而使用CustomScrollView
组件作为滚动容器,SliverList
和SliverGrid
分别替代List
和Grid
作为CustomScrollView
的子组件,滚动效果再由CustomScrollView
统一控制,这样就可以了。
但是需要注意的是由于CustomeScrollView
的子组件只能是Sliver
系列,所以如果你想将一个普通组件塞进CustomScrollView
,那么务必将该组件用SliverToBoxAdapter
包裹
要同时滚动ListView和GridView的时候可以使用SliverList和SliverGrid
SliverList需要和CustomScrollView配合使用
delegate:SliverChildDelegate 系统提供个两个已经实现好的代理:
SliverChildListDelegate/SliverChildBuilderDelegate
花样多变的SliverPersistentHeader
通过SliverPersistentHeader
,我们还可以实现sticky
吸顶的效果。
SliverPersistentHeader
最重要的一个属性是SliverPersistentHeaderDelegate
,为此我们需要实现一个类继承自SliverPersistentHeaderDelegate
。
class StickyTabBarDelegate extends SliverPersistentHeaderDelegate {
@override
double get minExtent => null;
@override
double get maxExtent => null;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => null;
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => null;
}
可以看到,SliverPersistentHeaderDelegate
的实现类必须实现其4个方法。其中:
-
minExtent
:收起状态下组件的高度; -
maxExtent
:展开状态下组件的高度; -
shouldRebuild
:类似于react
中的shouldComponentUpdate
; -
build
:构建渲染的内容。
不过SliverPersistentHeader
的神奇可远不止如此哦~我们可以通过它自定义一些头部的过渡效果,毕竟SliverAppBar
也是通过它实现的,
那么这种效果要如何实现呢?关键就在于build
方法中的shrinkOffset
属性,它代表当前头部的滚动偏移量。我们可以根据它计算得到当前收起头部的背景颜色
以及图标和文案的字体颜色
,这样就能根据当前位置得到过渡效果啦~
源码地址https://blog.51cto.com/jianguo/5022953
- 点赞
- 收藏
- 关注作者
评论(0)