关于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)