ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Flutter鸿蒙开发:从零搭建首页基础布局的完整指南

Flutter鸿蒙开发:从零搭建首页基础布局的完整指南 Flutter鸿蒙开发指南五实现首页基础布局这已经是系列的第五篇了。前面我们把环境搭好、工程跑通、模板工程里那套默认计数器页面也看明白了但说实话那东西离一个能看的App还差十万八千里。这篇文章就来干正事用Flutter在鸿蒙设备上把首页的基础布局搭出来。如果你正准备做鸿蒙应用又不想Android和鸿蒙各写一套UI那Flutter这条跨端路线值得好好研究一下。这篇文章会从页面骨架、数据模型、顶部搜索区、功能宫格、推荐列表几个维度完整拆解首页布局的实现过程顺带把我在鸿蒙真机上踩过的几个坑也一并交代清楚。Flutter的跨端能力在鸿蒙生态里已经不算什么新鲜概念了但真正动手写过的人都能感觉到它跟Android、iOS上的表现还是有不少差异。鸿蒙的窗口管理、返回手势、边缘触控、安全区策略都有自己的脾气这就意味着你不能直接把为Android写的布局原封不动丢过去。本篇文章的所有代码我都基于OpenHarmony适配的Flutter版本在真机上跑过你照着敲基本不会出大问题。如果你是第一次接触Flutter鸿蒙开发建议先把前几篇的环境配置和工程结构看完再回来不然有些约定俗成的概念可能会让你卡壳。1. 项目背景与布局方案选型1.1 为什么用Flutter做鸿蒙首页选Flutter来做鸿蒙应用核心诉求就一句话一套Dart代码同时覆盖Android、iOS和鸿蒙三条产品线。鸿蒙生态目前已经有不少自己的原生UI框架和声明式开发范式但如果你所在的公司跟我的情况类似——Android、iOS存量代码都是Flutter写的那新增鸿蒙端最经济的方式自然是让Flutter跑起来而不是另起炉灶用ArkUI重写一套界面。当然这个选择不是没有代价的。鸿蒙版本的Flutter在部分系统能力上还没有做到完全对齐比如原生地图、推送、支付这类强依赖厂商SDK的能力目前还是得通过平台通道去桥接。但首页这种以展示为主、交互不复杂的基础布局Flutter完全能胜任。而且布局代码的复用率极高——UI结构、间距、字体、颜色、逻辑在三个平台完全一致后续维护成本会低很多。1.2 首页布局的整体设计思路我这次要做的首页布局按照现在App的惯例分成三个主要区域顶部搜索区、功能入口宫格区、推荐内容列表区。顶部放App标题和搜索框中间放高频功能入口底部是流式推荐内容。整个页面用Column做垂直方向的主轴排列中间推荐列表用Expanded包裹让列表在剩余空间内自由伸缩滚动而不是整页套一个SingleChildScrollView。这里有个关键选型逻辑如果你把GridView、ListView全部塞进SingleChildScrollView那所有子列表的懒加载机制会全部失效数据量稍微大一点就会卡顿。Expanded加独立滚动容器是这种页面的正确打开方式。布局组件的选型上我坚持用最基础的Flutter组件Scaffold、SafeArea、Container、Column、Expanded、ListView、GridView。很多人一上来就堆第三方库比如flutter_screenutil做适配、get或者provider做状态管理这都没问题但首页骨架阶段我不建议这么干。先把原生组件用明白搞清楚Flex布局的伸缩规则、GridView的跨轴比例计算、ListView的缓存策略后面再接第三方库你会非常清楚它们帮你省了哪些事、做了哪些事。2. 首页结构设计与数据准备2.1 页面的三层结构拆分动手写代码之前先把页面拆清楚。这一步如果偷懒后面所有布局代码都会改得脑壳疼。我习惯用一叠便利贴把页面可视区域逐块写下来然后标注层级关系和布局方式。这次的首页我拆成三层第一层是顶部标题区高度约56像素左边显示“今日推荐”右侧放一个消息图标按钮。这个区域不需要滚动固定在最上方用Container包Row实现。第二层是搜索框高度44像素左右圆角16浅灰背景左侧放大镜图标加“搜索你感兴趣的内容”占位文字。在鸿蒙平板上运行的时候搜索框宽度要限制一下不能让它无限拉长。第三层是功能宫格加推荐列表。功能宫格我用GridView实现推荐列表用ListView。之所以把功能宫格放在可以滚动的区域内是因为如果首页后面做拉长宫格可以跟着上滑消失而不是固定在屏幕中间挡住推荐内容的视线。三层结构确定之后整个页面就是SafeArea包ColumnColumn里第一个元素是标题区第二是搜索框第三是Expanded展开的滚动区域。2.2 数据模型的占位设计布局阶段不需要接真实接口但数据模型得先定义好这样后面接业务时不用返工。我建了一个简单的首页模型类包含标题、副标题、标签、封面颜色四个字段class HomeItem { final String title; final String subtitle; final String tag; final Color coverColor; const HomeItem({ required this.title, required this.subtitle, required this.tag, required this.coverColor, }); }封面为什么用颜色而不是图片因为布局阶段用网络图片会有加载延迟和失败问题用色块可以精准验证间距、圆角、阴影这些布局参数。等真实接口通了把coverColor换成coverUrl就行。功能宫格的数据更简单一个标题加一个图标。图标我用的是Material内置的Icons集合省去引入额外图标库的麻烦。功能入口初期先放六个美食、出行、购物、影音、读书、生活。item数量是6GridView每行3列刚好两行视觉上很整齐。2.3 占位数据与实际数据的衔接方式首页数据我建议在布局阶段用私有方法生成不搞复杂的Repository层。比如在State里写一个_buildMockData()方法返回6个Item。等后端接口就绪了再把这个方法替换成网络请求。这样做的核心好处是布局和联调可以并行推进互不阻塞。我在这个项目里就是这么干的界面写完当天就能在真机上跑起来看效果不会因为没有接口就卡死在等待状态。后面接接口时也只是改数据源的位置UI层零改动。这种“先静态后动态”的开发节奏在多人协作时尤其重要。3. 核心布局实现与代码逐段解析3.1 页面整体骨架搭建骨架代码是首页布局的底座这里我直接贴出完整结构class HomePage extends StatefulWidget { const HomePage({super.key}); override StateHomePage createState() _HomePageState(); } class _HomePageState extends StateHomePage { final ListHomeItem _recommendList []; override void initState() { super.initState(); _mockList(); } void _mockList() { _recommendList.addAll([ HomeItem( title: Flutter 3.7 新特性解读, subtitle: 聊聊 Impeller 渲染引擎对鸿蒙适配的影响, tag: 技术, coverColor: const Color(0xFF4A6CF7), ), // ...... 这里可以继续添加多条数据 ]); } override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFFF5F6FA), body: SafeArea( child: Column( children: [ _buildTopBar(), _buildSearchBar(), Expanded( child: ListView( children: [ _buildFunctionGrid(), const SizedBox(height: 8), _buildRecommendHeader(), ..._buildRecommendList(), ], ), ), ], ), ), ); } }注意到一个关键点了吗我没用ListView.builder而是用ListView加展开操作符直接铺子组件。为什么因为首页结构里有GridView、标题区、列表卡片等多个不同类型的子区域交错排列用普通的ListView配合children展开更直观代码可读性也更好。等推荐列表体量变大、超过几十条的时候再考虑换成ListView.builder或CustomScrollView加SliverList的进阶方案。布局阶段简单可读优先。3.2 顶部标题栏的实现细节顶栏结构极其简单但有一个细节值得注意Widget _buildTopBar() { return Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 12), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 今日推荐, style: TextStyle( fontSize: 24, fontWeight: FontWeight.bold, color: Color(0xFF1D2329), ), ), GestureDetector( onTap: () { // 后续处理消息跳转 }, child: Container( width: 40, height: 40, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), ), child: const Icon(Icons.notifications_none, color: Color(0xFF4A6CF7), size: 22), ), ), ], ), ); }这40像素的圆形消息按钮容器颜色是纯白背景是浅灰这样即使不做阴影也能浮出层次感。消息按钮的点击区域比图标本身大热区40像素符合移动端最小触摸目标建议。很多新手刚写时直接放一个Icon完事用户在鸿蒙真机上手指粗的特别容易点不到这种体验问题在布局阶段就应该杜绝。3.3 搜索框的布局与样式搜索框这里有几个参数需要仔细说明Widget _buildSearchBar() { return Container( margin: const EdgeInsets.fromLTRB(16, 4, 16, 12), padding: const EdgeInsets.symmetric(horizontal: 12), height: 44, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), border: Border.all(color: const Color(0xFFE5E8EF), width: 1), ), child: const Row( children: [ Icon(Icons.search, size: 20, color: Color(0xFF8A949F)), SizedBox(width: 8), Text( 搜索你感兴趣的内容, style: TextStyle(fontSize: 14, color: Color(0xFF8A949F)), ), Spacer(), Icon(Icons.tune, size: 20, color: Color(0xFF8A949F)), ], ), ); }高度44是我实测比较合适的值。太矮了视觉上很局促太高了占纵向空间。圆角12在鸿蒙平板上看起来是略微收敛的弧度比16的超级圆角更有质感。右侧的tune图标是筛选入口的预设现在摆着不用管后续要加搜索条件筛选时直接用。搜索框我没有用TextField而是先用静态样式占位。为什么因为布局阶段你关注的应该是高度、圆角、字体、间距这些视觉参数如果放了TextField进去默认的输入光标、获取焦点后的样式变化会让你分不清到底是在调布局还是在调交互。等布局稳定了再替换成真正的输入组件一步到位。3.4 功能入口宫格的实现与比例计算宫格区是整个首页布局中参数计算最讲究的地方直接贴代码Widget _buildFunctionGrid() { ListMapString, dynamic items [ {icon: Icons.restaurant, name: 美食}, {icon: Icons.directions_bus, name: 出行}, {icon: Icons.shopping_bag, name: 购物}, {icon: Icons.movie, name: 影音}, {icon: Icons.menu_book, name: 读书}, {icon: Icons.favorite, name: 生活}, ]; return Container( margin: const EdgeInsets.symmetric(horizontal: 16), padding: const EdgeInsets.symmetric(vertical: 16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), ), child: GridView.count( crossAxisCount: 3, shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), mainAxisSpacing: 12, crossAxisSpacing: 12, padding: EdgeInsets.zero, children: items.map((item) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: 44, height: 44, decoration: BoxDecoration( color: const Color(0xFFF0F3FF), borderRadius: BorderRadius.circular(12), ), child: Icon(item[icon], size: 22, color: const Color(0xFF4A6CF7)), ), const SizedBox(height: 8), Text( item[name], style: const TextStyle(fontSize: 13, color: Color(0xFF3D434A)), ), ], ); }).toList(), ), ); }两个核心参数必须解释清楚第一shrinkWrap: true。这个属性让GridView的高度根据内容自适应而不是默认占满可用高度。外层是ListView如果GridView不设置shrinkWrap高度会冲突运行时你会在控制台看到关于无限高度的警告实际表现是宫格区域被压缩成一坨或者直接不显示。第二NeverScrollableScrollPhysics。它的作用是禁止宫格内部滚动保证所有滑动交互都由外层ListView接管。如果你忘记设置在嵌套滚动时会出现手势竞争一会儿是宫格在滚一会儿是列表在滚体验非常分裂。图标容器固定44乘44背景色用浅蓝紫图标颜色用主色蓝整体视觉一致性好。这个配色大家可以按自己产品的主视觉来调重点是把“容器、图标、文字”三件套的比例固定下来。我特意测试过不同屏幕尺寸在360dp宽度的手机上3列宫格每个item宽度约100dp44dp的图标加8dp间距加13号字视觉重心刚好在中间。3.5 推荐列表的卡片布局实现推荐区的标题区很简单“热门推荐”加一个“查看更多”跳转文本。重点在卡片布局。下面是推荐卡片的构建方法Widget _buildRecommendItem(HomeItem item) { return Container( margin: const EdgeInsets.fromLTRB(16, 6, 16, 6), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: const [ BoxShadow( color: Color(0x14000000), blurRadius: 8, offset: Offset(0, 2), ), ], ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 96, height: 96, decoration: BoxDecoration( color: item.coverColor, borderRadius: const BorderRadius.horizontal( left: Radius.circular(16), ), ), child: const Icon(Icons.article, size: 32, color: Colors.white54), ), Expanded( child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.title, maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFF1D2329), height: 1.3, ), ), const SizedBox(height: 6), Text( item.subtitle, maxLines: 2, overflow: TextOverflow.ellipsis, style: const TextStyle( fontSize: 13, color: Color(0xFF8A949F), height: 1.4, ), ), const SizedBox(height: 8), Container( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration( color: const Color(0xFFF0F3FF), borderRadius: BorderRadius.circular(4), ), child: Text( item.tag, style: const TextStyle(fontSize: 11, color: Color(0xFF4A6CF7)), ), ), ], ), ), ), ], ), ); }卡片的左侧封面图区域我用的是96乘96固定宽高加BorderRadius.horizontal只圆左边两个角这样封面和卡片的整体圆角可以平滑过渡不会出现直角切圆角的视觉断层。右侧正文区用Expanded自动展开保证标题、副标题、标签的纵向排列始终有足够的空间。这里最容易犯的错是什么把整个卡片包在InkWell里然后左边封面、右边内容都用各自的Container忽略了clipBehavior。添加点击水波纹效果时波纹溢出圆角边界那视觉效果可以用“灾难”来形容。解决办法是给外层Container加clipBehavior: Clip.antiAlias或者在Decoration里统一处理圆角后确保所有子widget不越界。3.6 间距与圆角参数的计算逻辑布局参数表面上是经验值实际上背后有视觉逻辑可循。我整理了一个自查表每次布局完成我都会对照检查一遍页面左右安全边距16像素这是目前绝大多数移动端页面采用的基础间距保证内容不会顶到屏幕边缘。卡片之间的垂直间距12像素卡片内部元素间距6到8像素不等这个梯度是有讲究的内容内部的关系用细间距6/8内容块之间的关系用粗间距12/16这样用户扫视时能自然区分信息层级。圆角的使用遵循“层级越高、圆角越大”的原则外层卡片圆角16图标容器圆角12标签圆角4。如果反过来标签比卡片还圆整体就会失去统一感。字号的梯度同样重要标题15号、正文13号、标签11号层级递减权重递减。这套规则说起来简单但很多初学者布局看起来“不够精致”差的就是这种刻度感。4. 常见问题与鸿蒙适配踩坑实录4.1 列表嵌套与滚动冲突的解决方案这是我第一次在鸿蒙真机上跑首页时遇到的头号问题。现象是功能宫格在ListView内部滚动时手指滑动经常“卡住”页面有时完全无响应有时候又突然跳一大截。问题根源在上面已经提到过——GridView默认的滚动Physics与外层ListView冲突。解决方式就是3.4里那段代码的NeverScrollableScrollPhysics。除此之外还有一点容易被忽略ListView的cacheExtent参数。这个参数控制列表预加载区域的高度默认为0。在鸿蒙设备上由于屏幕翻转、窗口尺寸变化等场景较频繁建议显式设置一个值比如250让列表提前构建可视区域外的少量item滑动时会顺滑很多。如果你在后续开发中遇到比宫格嵌套更复杂的场景比如TabBarView里套列表那就要考虑用CustomScrollView加SliverGrid、SliverList来统一管理滚动。我这次没有用是因为首页整体结构简单杀鸡不用牛刀。4.2 文本溢出的定位与修复布局写完在iOS和Android模拟器上都看不出问题上了鸿蒙真机某些卡片标题特别长时直接显示“...”有些则出现RenderFlex overflowed的黄黑条纹。排查这类问题我有一套固定的流程第一步在Flutter Inspector里打开Debug Paint可以非常直观地看到哪个RenderBox超出了边界。第二步定位到具体的Text组件检查是否设置了maxLines和overflow。第三步检查Text所在父组件是否为Flexible或Expanded如果没有在Row中它会按自身宽度参与布局导致溢出。我最终给推荐卡片的所有文字都加了两行限制和ellipsis策略。副标题最多显示2行标题最多2行超出自动省略。同时给Row的crossAxisAlignment设置了start避免左侧封面和右侧文字在高度不一致时出现拉伸变形。这个修复方案在所有测试设备上一劳永逸。4.3 鸿蒙安全区与状态栏适配鸿蒙设备的屏幕形态非常杂有挖孔屏、刘海屏、曲面屏还有形形色色的折叠屏。如果你的页面没有做安全区适配内容会被状态栏、挖孔、胶囊区域遮挡。Flutter的SafeArea组件在鸿蒙上表现尚可但有几个坑第一SafeArea默认只读取MediaQuery的padding信息。鸿蒙某些设备的横竖屏切换过渡动画中padding信息会短暂丢失页面顶栏会瞬间跳动。解决方法是给顶栏加一个固定的最小高度或者用AnnotatedRegion重新声明系统UI样式。第二SafeArea包在Scaffold的body外层但底部如果后续接入导航栏要注意BottomAppBar与SafeArea的叠加关系。我在首页阶段就把body整体包了SafeArea底部暂时留白后续做底部导航时再单独处理BottomNavigationBar的bottomNavigationBar属性让它自己适配安全区。4.4 热重载与Impeller渲染引擎的注意点开发过程中来回改样式热重载是日常。但在鸿蒙上Flutter的Impeller渲染引擎目前还存在一些兼容性问题。我自己遇到过一次改完代码热重载后页面出现大面积黑色闪烁重启App又恢复正常。如果你在鸿蒙设备上遇到类似现象不要怀疑代码逻辑直接冷启动就好。另外一个与Impeller有关的点是某些复杂的圆角裁剪、阴影叠加在开启Impeller后会出现渲染瑕疵。用Impeller渲染引擎时如果某些组件的阴影参数异常建议检查是否在Container的decoration中同时使用了borderRadius和boxShadow这两个属性组合是阴影渲染错误的常见触发点。我的卡片阴影配置在Impeller模式下实测正常但如果你用的Flutter版本较新建议在真机上多做几轮渲染测试。4.5 常见问题排查速查表整理一个我自己常用的速查表开发中遇到类似问题直接照方抓药症状可能原因解决方案宫格区域被压缩或不可见GridView外层无shrinkWrap设置shrinkWrap为true滑动卡顿、手势竞争嵌套滚动冲突内层滚动加NeverScrollableScrollPhysics文本“...、黑黄条纹”Text溢出不限行设置maxLines TextOverflow.ellipsis页面顶栏跳动状态栏高度切换固定最小高度或AnnotatedRegion热重载后黑屏闪烁Impeller渲染缓存问题冷启动无需改代码卡片圆角处水波纹溢出缺少裁剪设置clipBehavior: Clip.antiAlias分组按钮无分割线列表视觉混乱自定义间隔组件或分割线组件4.6 鸿蒙真机与Android模拟器的渲染差异鸿蒙真机的屏幕PPI、系统字体缩放、窗口Insets策略跟Android模拟器差异不小。最典型的一个坑是Android模拟器里完美的布局在鸿蒙真机上字变大了、间距变宽了、甚至按钮被顶出屏幕。鸿蒙的字体缩放策略会对Flutter的Text产生直接影响。如果你的应用不想跟随系统字体缩放需要在MaterialApp里设置builder对MediaQuery的textScaler做限制。我处理首页布局时的做法是主要字体固定用fontSize不做自适应缩放测试时分别在系统字体标准、大号、特大号三种模式下验证布局不变形。这个逻辑不是所有项目都适用如果你的产品要求完美适配超大字体那就得反过来用自适应布局。另外鸿蒙的窗口尺寸调整动画比Android模拟器更频繁尤其是在分屏模式下。所以在我的布局里Flexible和Expanded的正确使用比固定宽高更关键因为窗口一变只有弹性布局能扛住。5. 布局完成后的交互与状态管理规划5.1 从静态布局到动态交互首页布局写完接下来的核心工作就是让页面“活”起来。第一步是把静态的搜索占位改成真实的输入框第二步是给功能宫格的每个入口绑定点击事件第三步是推荐卡片点击跳转详情页。这些交互的接入点在当前布局中都已经预留好了用GestureDetector或InkWell包住对应组件即可。功能宫格的点击处理建议放在GridView的onTap回调中统一管理而不是每个item单独包一层GestureDetector。这样后续做埋点、跳转逻辑时会有一个统一的入口函数代码可维护性好很多。5.2 组件通信与状态管理的引入时机很多人在布局阶段就开始纠结用Provider还是Riverpod还是GetX。我的建议是如果页面内状态实在简单先用setState完全够用。首页最典型的状态就是推荐列表数据、搜索关键词、加载状态。这些都属于页面级状态setState配合FutureBuilder就能解决。什么时候该引入第三方状态管理当你开始跨页面共享数据时比如登录状态、购物车数量、用户偏好设置。那种情况下再上Provider或Riverpod不迟。我当前的首页布局中所有交互都是页面内部闭环强行引入状态管理框架反而增加心智负担。5.3 布局性能的初步检查思路布局完成后在鸿蒙真机上我习惯做一次性能初检。打开DevTools的Performance Overlay重点观察两件事一是Build耗时二是Raster耗时。如果Raster耗时过高说明布局中可能存在过度绘制或复杂阴影。首页这种简单布局正常应该保持在毫秒级。另外建议打开DebugProfile模式而非Debug模式测试因为Debug模式下的性能数据会严重失真很多在Debug下看起来很慢的操作Profile模式下其实完全没问题。还有一个我踩过的小坑如果你在DevTools里看到首页的RepaintBoundary数量异常大概率是因为卡片阴影和圆角在交叉作用。可以尝试在列表卡片外包一层RepaintBoundary减少重绘区域。这个优化属于锦上添花初期布局不需要过度优化但知道这个方向是有必要的。6. 布局延展与后续迭代建议6.1 从固定列表到分页加载当前推荐列表的数据是本地Mock后续接接口后一定会遇到分页场景。我的建议是提前在列表底部预留一个加载状态组件上拉到底部时显示加载中数据加载完显示“已经到底了”出现错误则显示“点击重试”。这些UI状态可以在布局阶段就写好后续只需要通过状态控制显隐。分页加载的核心逻辑是监听ListView的滚动位置当滚动到列表末尾一定距离比如还剩200像素时触发下一页加载。这个距离可以通过ScrollController的position.extentAfter计算得到。Flutter在2.x版本开始推荐的Scrollable监听方式在鸿蒙上也表现正常没有遇到兼容性问题。6.2 组件复用与代码组织随着首页越做越复杂把每个区块抽成独立Widget是必然趋势。我的建议是让HomePage只做组装工作具体的区块组件单独建一个widgets/文件夹存放。比如HomeSearchBar、HomeFunctionGrid、HomeRecommendCard各自独立成文件参数通过构造函数传入。这样几个页面复用时直接引入组件即可而不是复制粘贴一大段代码。我的经验是每个组件文件尽量控制在100行以内超过就继续拆分。拆分粒度太粗会让文件变成什么都有的“杂货铺”太细又会造成组件数量过多、参数传递混乱。对于首页这种展示型页面按功能区块拆分是最合理的粒度。6.3 留出主题定制空间多主题支持是现代App的标配首页布局中颜色、字体、间距这些样式值就应该避免散落各处。我建议初期就定义一个AppColors类统一定义主色、辅色、背景色、文本色等常量。当前布局中的0xFF4A6CF7主色在代码里出现了多次虽然现在没有改主题的需求但提前收敛到常量后续做深色模式的成本会低很多。不要等颜色在几十个文件里散落一地时才想起重构那时候改一个色值会让你怀疑人生。这次首页基础布局从结构拆分到代码实现再到鸿蒙真机适配的完整链路能跑通的底层逻辑其实不算复杂组件选型服务于布局结构布局结构服务于页面内容层次参数设定服务于视觉统一。在鸿蒙设备上调试Flutter布局最大的心得是“不要只相信模拟器真机才是检验真理的唯一标准”很多状态栏跳动、渲染颜色偏差、字体缩放问题都是在真机上才能暴露出来的。特别是Impeller渲染引擎在鸿蒙上的表现还在持续优化中建议多关注Flutter官方版本发布说明有稳定新版本就及时升级。布局做扎实了后面的交互、动画、状态管理才有稳步推进的基础。
返回列表