本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!
这是 《Flutter 工程化框架选择》 系列的第二篇 ,就像之前说的,这个系列只是单纯告诉你,创建一个 Flutter 工程,或者说搭建一个 Flutter 工程脚手架,应该如何快速选择适合自己的功能模块,或者说这是一个指引系列,所以比较适合新手同学。
本篇主要介绍 UI 相关的,但是完全单纯介绍 UI 好像又有点水,那就是加一些小知识来吸吸水分吧。
做为前端开发,我们的大部分职责就是开发 UI ,但是如果有人帮我们提前把 UI 做好,那岂不美哉?事实上很多时候 UI 确实是可以模版化,而前端领域也一直是这样,例如 Ant Design
、Element-UI
等 ,那 Flutter 上是否也有这样的支持?
答案肯定是有的,但是在介绍它们之前,我们先聊一个 Flutter UI 的问题:嵌套。
为了不太水,我们前言聊技术,后半部分推荐项目。
谈到 Flutter 肯定就有人说嵌套,是的, Flutter 本身就是通过直接嵌套 Widget
来渲染 UI , 所以大家可能就会吐槽类似下面的代码,虽然这段代码没有意义,但是这里我们要先思考两个问题:
- Flutter 怕不怕
Widget
嵌套影响性能? - Flutter 有没有办法解决嵌套?
首先第一点就是,Flutter 一般情况下不怕嵌套影响性能,因为 “众所周知” 的原因,Flutter 里的 Widget
并不是真正的控件,我更愿意说 Widget
是配置文件,真正的绘制和布局对象是它背后的 RenderObejct
等相关逻辑。
嵌套层级看起来很多的原因,是因为
Widget
颗粒度太细。
当然这个还要看你嵌套的 Widget
做了什么?或者说是嵌套的 Widget
的 RenderObject
做了什么,例如:
Padding
的RenderPadding
就是在 layout 时多了一个Size
和childParentData.offset
计算ColoredBox
的_RenderColoredBox
就是多一句drawRect
Align
的RenderPositionedBox
就是多计算一个childParentData.offset
所以这些 Widget
的颗粒度很细,但是也很轻,我们直接用的时候可能会一层一层嵌套,看起来不美观,但是实际渲染时对性能影响不大。
当然,并不是所有的
Widget
都很轻不怕嵌套,例如Clip
、Transform
和Opacity
等,如果涉及到pushLayer
等操作时,在需要做图层合成的时候,那确实对性能影响还是比较大的。
那第二个问题,如何解决嵌套?这时候你就需要 “配置模版” ,通过封装来优化代码结构。
“配置模版”是什么意思?举个例子 : Container
应该用过吧? Container
其实就是官方给大家准备的 “模版” ,它本身只是一个 StatelessWidget
,也就是一个没有 RenderObject
的 Widget
,它靠的就是把各种功能的 Widget
组合起来使用,如下图就是使用 Container
的对比情况。
所以在使用 Flutter 构建 UI 时,就可以谈及到两个点:
Widget
是配置文件,它一般很轻,不怕嵌套,真正绘制渲染的是它背后的RenderObject
- 通过各种 UI 配置模版来解决嵌套,特别是抽象出适合自己业务逻辑的 UI 模版
举个例子,如下方的第三方开源布局包 dashboard ,在这种复杂的 UI 布局上难道就靠直接一级一级嵌套 Column
和 Row
来解决?答案肯定不是!
dashboard 的是通过 Stack
+ Positioned
组成模版,在手势移动时计算,通过 AnimatedBuilder
实现动画偏移,自动计算控件位置。
其实也可以直接用
AnimatedPositioned
,具体可见 《Flutter 小技巧之有趣的动画技巧》
所以可以看到, Flutter 里你其实可以不那么嵌套,具体还是看你的封装方式,除了这样,还有就是直接在 RenderObject
上进行自定义布局,比如下方这两个例子:
cloud | custom_multi_render |
---|---|
你说上面的布局用 Stack
+ Positioned
的模式能不能做?肯定是可以,但是在 RenderObject
层实现不是更优雅吗?把脏活累活写在 RenderObject
, 通过 Widget
提供配置接口,这样就不会一上来就向用户露 “底裤” 不是么。
所以,把眼界打开,不要什么都盯着
Widget
嵌套,往RenderObject
层面探索,你会发现 Flutter 其实不像表面那么浮躁,再不济来尝试下CustomMultiChildLayout
,它也可以帮助你解决一些复杂布局下的嵌套问题。
当然,还有一些项目另辟蹊径,比如 niku ,这个项目通过 typedef
和抽象拓展,利用语法对官方控件进行二次封装,实现创建了一个 “非正道” 的 UI 配置效果,具体如下图所示,喜不喜欢就看个人爱好了,但是它确实一定程度解决了嵌套可视化的问题。
作者是个二次元,但是看地址他应该是泰国哥们
当然,我们这一期的关键是提高 UI 生产力,单说源码实现就没劲了,所以重点让我们看后半部分。
在前端领域,使用统一的 UI 套件可以加快开发的节奏,减少开发和设计之间的摩擦,而且风格统一。一般情况下,在企业内部都是在不知不觉中沉淀下来各种组件,最后形成组件池,从而落地成 UI 套件。
比如贝壳的 bruno ,我愿意称它为 Flutter 界的 Element-UI
,目前已经支持到 Flutter 3 ,作为少有国内大厂维护的 Flutter UI 项目,甚至它还提供了 sketch 设计指引 和 设计物料下载 。
bruno | getwidget | fsuper |
---|---|---|
当然,除了 bruno 之后,像 getwidget 、 fsuper 也提供了日常开发中常用的 UI 套件,虽然风格风格上可能并没有 bruno 统一,但是还是可以在一定程度提高开发的生产力。
事实上对于个人开发者来说,这种套件可以解决很多设计上的问题。
另外聊到 Flutter UI 套件就要一定要介绍国内的 fluttercandies 组织,fluttercandies 是由大佬们共同维护的一系列 Flutter 开源项目,记住,是大佬们,并且一直在持续更新:
- extended_image
- extended_nested_scroll_view
- extended_text
- extended_text_field
- extended_list
- extended_sliver
- extended_tabs
- wechat_assets_picker
- waterfall_flow
举个例子,如果 flutter framework 短期不能解决的问题,那就大佬就会 cv 一份控件自己维护,这就是 fluttercandies 的节奏和优势。
既然介绍 Flutter UI ,就不得不介绍 PC 相关的风格的 UI ,因为 Flutter 不只是 Android 和 iOS ,它还支持 Web 和 PC, 所以类似 PC 的 UI 风格也值得推荐,比如 ant_design_flutter 就是一个很有意思的项目。
fluent_ui | macos_ui | ant_design_flutter |
---|---|---|
那有的人可能就说,我想要一套代码适配多平台的屏幕尺寸行不行?答案肯定是可以的,下面这几个 package 就提供了不同屏幕尺寸下一套代码的动态适配方案,我个人可能会比较喜欢 ResponsiveFramework 。
ResponsiveFramework | responsive_sizer | flutter_adaptive_ui |
---|---|---|
这类 Appbar 的实现其实是我被问过最多的,其实它的核心实现都是 Sliver ,严格意义上我觉得并不需要第三方库,自己用 Sliver 就可以实现,但是本着能不动手就不动手原则,也推荐几个库吧:
draggable_home | extended_sliver | scroll_app_bar |
---|---|---|
gsy_flutter_demo 里也提供了几种实现思路,其实并不复杂。
可能有人会觉得,不会吧不会吧, Drawer 也需要第三方库?
还真有,因为有时候可能需要不一样的动画效果,另外这里的 sidebarx
,也和官方提供的 NavigationRail
有异曲同工之妙,能在 UI 上适配多平台的操作习惯。
sidebarx | flutter_advanced_drawer | curved_drawer |
---|---|---|
既然都说到 Drawer
,那 Tabbar
也提供几个花里胡哨的动画效果,主要是切换时的动画效果,另外 tab_container
可能算是比较有意思的库,用的 Path
来编绘背景动画效果。
flutter-cupertino-tabbar | tab_indicator_styler | tab_container |
---|---|---|
说到 Tabbar
相对应的还有 BottomBar 相关,这里也提供几个库,主要是动画效果很有趣,我个人还是挺喜欢这种曲线的动画效果。
curved_navigation_bar | salomon_bottom_bar | bubble_bottom_bar |
---|---|---|
启动指引这个需求,正常情况下一个 PageView
就可以满足产品经理的场景,但是有时候可能会需要你来“亿”点点动画效果来增加 KPI,所示拿着也许就对你有用了,当然你也可以把它当作 PageView
动画来使用。
concentric_transition | nice_intro | intro_views_flutter |
---|---|---|
这个应该无需多言了,基本上 App 都会需要用到,这两个库基本覆盖了 90% 的场景
flutter_badges | corner_decoration |
---|---|
这个可能一般情况下大家都不需要这么花里胡哨的效果,但是万一呢?Material 风格上这种交互还是挺多的,不过国内对 Material 确实不是很感冒。
flutter_animated_button | progress_state_button |
---|---|
没想到吧?头像为什么还需要库?
其实就是下面的这个场景,相信这个场景可能大家都不会陌生,有社交需求的时候,经常会存在这样的 UI ,掘金沸点不也有类似 UI 么?
avatar_stack | overflow_view | |
---|---|---|
这个需求可能一般人不会需要,推荐它是因为我还记得几年的时候,收了 1000 给人做了这样的一个外包,就是做一个这样的控件。
swipe_deck | swipeable_card_stack | appinio_swiper |
---|---|---|
这其实更多是一个 Route 相关的动画效果,感觉好像国内也不常用到,但是之前确实有好几次咨询有没有类似的实现。
we_slide | sliding_up_panel |
---|---|
这是我在群里被问过好多次的一个需求场景,我也不知道为什么那么多应用会需要用到这样的 UI ?不过这类需求自己从头实现确实会比较费事。
timeline_tile | timelines |
---|---|
好了,关于 Flutter UI 相关的内容推荐就到这里,本篇主要还是提供给大家如何理解 Flutter 的 UI 布局,并且尽可能去解决嵌套,同时提供一些有意思的第三方 package ,进一步提高大家开发 UI 的生产力。
最后,如果你还有什么关于 Flutter 工程或者框架的疑问,欢迎留言评论,也许新的素材又有了~