Flutter 工程化框架选择 — 搞定 UI 生产力

25,148 阅读9分钟
本文为稀土掘金技术社区首发签约文章,14天内禁止转载,14天后未获授权禁止转载,侵权必究!

这是 《Flutter 工程化框架选择》 系列的第二篇 ,就像之前说的,这个系列只是单纯告诉你,创建一个 Flutter 工程,或者说搭建一个 Flutter 工程脚手架,应该如何快速选择适合自己的功能模块,或者说这是一个指引系列,所以比较适合新手同学。

本篇主要介绍 UI 相关的,但是完全单纯介绍 UI 好像又有点水,那就是加一些小知识来吸吸水分吧

做为前端开发,我们的大部分职责就是开发 UI ,但是如果有人帮我们提前把 UI 做好,那岂不美哉?事实上很多时候 UI 确实是可以模版化,而前端领域也一直是这样,例如 Ant DesignElement-UI 等 ,那 Flutter 上是否也有这样的支持?

答案肯定是有的,但是在介绍它们之前,我们先聊一个 Flutter UI 的问题:嵌套

为了不太水,我们前言聊技术,后半部分推荐项目。

前言- UI 嵌套

谈到 Flutter 肯定就有人说嵌套,是的, Flutter 本身就是通过直接嵌套 Widget 来渲染 UI , 所以大家可能就会吐槽类似下面的代码,虽然这段代码没有意义,但是这里我们要先思考两个问题:

  • Flutter 怕不怕 Widget 嵌套影响性能
  • Flutter 有没有办法解决嵌套

首先第一点就是,Flutter 一般情况下不怕嵌套影响性能,因为 “众所周知” 的原因,Flutter 里的 Widget 并不是真正的控件,我更愿意说 Widget 是配置文件,真正的绘制和布局对象是它背后的 RenderObejct 等相关逻辑

嵌套层级看起来很多的原因,是因为 Widget 颗粒度太细。

当然这个还要看你嵌套的 Widget 做了什么?或者说是嵌套的 WidgetRenderObject 做了什么,例如:

  • PaddingRenderPadding 就是在 layout 时多了一个 SizechildParentData.offset 计算
  • ColoredBox_RenderColoredBox 就是多一句 drawRect
  • AlignRenderPositionedBox 就是多计算一个 childParentData.offset

所以这些 Widget 的颗粒度很细,但是也很轻,我们直接用的时候可能会一层一层嵌套,看起来不美观,但是实际渲染时对性能影响不大。

当然,并不是所有的 Widget 都很轻不怕嵌套,例如 ClipTransformOpacity 等,如果涉及到 pushLayer 等操作时,在需要做图层合成的时候,那确实对性能影响还是比较大的。

那第二个问题,如何解决嵌套?这时候你就需要 “配置模版” ,通过封装来优化代码结构

“配置模版”是什么意思?举个例子 : Container 应该用过吧? Container 其实就是官方给大家准备的 “模版” ,它本身只是一个 StatelessWidget ,也就是一个没有 RenderObjectWidget ,它靠的就是把各种功能的 Widget 组合起来使用,如下图就是使用 Container 的对比情况。

所以在使用 Flutter 构建 UI 时,就可以谈及到两个点:

  • Widget 是配置文件,它一般很轻,不怕嵌套,真正绘制渲染的是它背后的 RenderObject
  • 通过各种 UI 配置模版来解决嵌套,特别是抽象出适合自己业务逻辑的 UI 模版

举个例子,如下方的第三方开源布局包 dashboard ,在这种复杂的 UI 布局上难道就靠直接一级一级嵌套 ColumnRow 来解决?答案肯定不是!

dashboard 的是通过 Stack + Positioned 组成模版,在手势移动时计算,通过 AnimatedBuilder 实现动画偏移,自动计算控件位置。

其实也可以直接用 AnimatedPositioned ,具体可见 《Flutter 小技巧之有趣的动画技巧》

所以可以看到, Flutter 里你其实可以不那么嵌套,具体还是看你的封装方式,除了这样,还有就是直接在 RenderObject 上进行自定义布局,比如下方这两个例子:

cloudcustom_multi_render
image-20220922120414245

你说上面的布局用 Stack + Positioned 的模式能不能做?肯定是可以,但是在 RenderObject 层实现不是更优雅吗?把脏活累活写在 RenderObject , 通过 Widget 提供配置接口,这样就不会一上来就向用户露 “底裤” 不是么

所以,把眼界打开,不要什么都盯着 Widget 嵌套,往 RenderObject 层面探索,你会发现 Flutter 其实不像表面那么浮躁,再不济来尝试下 CustomMultiChildLayout ,它也可以帮助你解决一些复杂布局下的嵌套问题。

当然,还有一些项目另辟蹊径,比如 niku ,这个项目通过 typedef 和抽象拓展,利用语法对官方控件进行二次封装,实现创建了一个 “非正道” 的 UI 配置效果,具体如下图所示,喜不喜欢就看个人爱好了,但是它确实一定程度解决了嵌套可视化的问题。

作者是个二次元,但是看地址他应该是泰国哥们

当然,我们这一期的关键是提高 UI 生产力,单说源码实现就没劲了,所以重点让我们看后半部分。

UI 套件

在前端领域,使用统一的 UI 套件可以加快开发的节奏,减少开发和设计之间的摩擦,而且风格统一。一般情况下,在企业内部都是在不知不觉中沉淀下来各种组件,最后形成组件池,从而落地成 UI 套件。

比如贝壳的 bruno ,我愿意称它为 Flutter 界的 Element-UI ,目前已经支持到 Flutter 3 ,作为少有国内大厂维护的 Flutter UI 项目,甚至它还提供了 sketch 设计指引设计物料下载

brunogetwidgetfsuper

当然,除了 bruno 之后,像 getwidgetfsuper 也提供了日常开发中常用的 UI 套件,虽然风格风格上可能并没有 bruno 统一,但是还是可以在一定程度提高开发的生产力。

事实上对于个人开发者来说,这种套件可以解决很多设计上的问题。

另外聊到 Flutter UI 套件就要一定要介绍国内的 fluttercandies 组织,fluttercandies 是由大佬们共同维护的一系列 Flutter 开源项目,记住,是大佬们,并且一直在持续更新:

举个例子,如果 flutter framework 短期不能解决的问题,那就大佬就会 cv 一份控件自己维护,这就是 fluttercandies 的节奏和优势。

PC

既然介绍 Flutter UI ,就不得不介绍 PC 相关的风格的 UI ,因为 Flutter 不只是 Android 和 iOS ,它还支持 Web 和 PC, 所以类似 PC 的 UI 风格也值得推荐,比如 ant_design_flutter 就是一个很有意思的项目

fluent_uimacos_uiant_design_flutter

Responsive

那有的人可能就说,我想要一套代码适配多平台的屏幕尺寸行不行?答案肯定是可以的,下面这几个 package 就提供了不同屏幕尺寸下一套代码的动态适配方案,我个人可能会比较喜欢 ResponsiveFramework 。

ResponsiveFrameworkresponsive_sizerflutter_adaptive_ui

Appbar

这类 Appbar 的实现其实是我被问过最多的,其实它的核心实现都是 Sliver ,严格意义上我觉得并不需要第三方库,自己用 Sliver 就可以实现,但是本着能不动手就不动手原则,也推荐几个库吧:

draggable_homeextended_sliverscroll_app_bar

gsy_flutter_demo 里也提供了几种实现思路,其实并不复杂。

Drawer

可能有人会觉得,不会吧不会吧, Drawer 也需要第三方库?

还真有,因为有时候可能需要不一样的动画效果,另外这里的 sidebarx ,也和官方提供的 NavigationRail有异曲同工之妙,能在 UI 上适配多平台的操作习惯。

sidebarxflutter_advanced_drawercurved_drawer

Tarbar

既然都说到 Drawer ,那 Tabbar 也提供几个花里胡哨的动画效果,主要是切换时的动画效果,另外 tab_container 可能算是比较有意思的库,用的 Path 来编绘背景动画效果。

flutter-cupertino-tabbartab_indicator_stylertab_container

BottomBar

说到 Tabbar 相对应的还有 BottomBar 相关,这里也提供几个库,主要是动画效果很有趣,我个人还是挺喜欢这种曲线的动画效果。

curved_navigation_barsalomon_bottom_barbubble_bottom_bar

指引

启动指引这个需求,正常情况下一个 PageView 就可以满足产品经理的场景,但是有时候可能会需要你来“亿”点点动画效果来增加 KPI,所示拿着也许就对你有用了,当然你也可以把它当作 PageView 动画来使用。

concentric_transitionnice_introintro_views_flutter

角标

这个应该无需多言了,基本上 App 都会需要用到,这两个库基本覆盖了 90% 的场景

flutter_badgescorner_decoration

动画按键

这个可能一般情况下大家都不需要这么花里胡哨的效果,但是万一呢?Material 风格上这种交互还是挺多的,不过国内对 Material 确实不是很感冒。

flutter_animated_buttonprogress_state_button

头像

没想到吧?头像为什么还需要库?

其实就是下面的这个场景,相信这个场景可能大家都不会陌生,有社交需求的时候,经常会存在这样的 UI ,掘金沸点不也有类似 UI 么?

avatar_stackoverflow_view

swipe 卡片

这个需求可能一般人不会需要,推荐它是因为我还记得几年的时候,收了 1000 给人做了这样的一个外包,就是做一个这样的控件。

swipe_deckswipeable_card_stackappinio_swiper

bottom sheet

这其实更多是一个 Route 相关的动画效果,感觉好像国内也不常用到,但是之前确实有好几次咨询有没有类似的实现。

we_slidesliding_up_panel

时间轴 UI

这是我在群里被问过好多次的一个需求场景,我也不知道为什么那么多应用会需要用到这样的 UI ?不过这类需求自己从头实现确实会比较费事。

timeline_tiletimelines

好了,关于 Flutter UI 相关的内容推荐就到这里,本篇主要还是提供给大家如何理解 Flutter 的 UI 布局,并且尽可能去解决嵌套,同时提供一些有意思的第三方 package ,进一步提高大家开发 UI 的生产力

最后,如果你还有什么关于 Flutter 工程或者框架的疑问,欢迎留言评论,也许新的素材又有了~