ARTICLE DETAIL

资讯详情

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

Flutter鸿蒙适配实战:自定义AppBar打造沉浸式顶部导航

Flutter鸿蒙适配实战:自定义AppBar打造沉浸式顶部导航 做跨平台开发的朋友应该都有感受Flutter 这套框架写 UI 确实爽一套代码双端运行性能也够顶。但真正让人头疼的往往不是业务逻辑而是那些看似简单、实际到处都是坑的基础控件——比如今天要聊的 AppBar。最近在把一款 Flutter 应用往鸿蒙HarmonyOS NEXT上迁移适配时我和顶部导航栏死磕了整整一阵子。合作方反馈的第一条意见就是“顶部导航太丑、交互也不对”。乍一听挺冤的Flutter 的 AppBar 明明自带 Material 风格怎么到了鸿蒙上就“丑”了深入做下去才发现这里面的学问远比想象中大。这篇文章不打算只讲 API 怎么调而是把我这段时间在鸿蒙环境下重构 AppBar、改造“顶部导航美学”的完整过程和盘托出。包括为什么系统自带的 AppBar 在鸿蒙上不够用、自定义 TopBar 时踩到的尺寸与状态栏适配坑、滚动渐变动画的实现细节、以及事件通道和页面状态保持这些容易翻车的地方。无论你是刚开始接触 Flutter 与鸿蒙适配还是已经在做跨端应用正在优化顶部导航这篇文章都值得看完。1. 内容整体设计与思路拆解为什么系统 AppBar 在鸿蒙上“失灵”了1.1 从“能用”到“好看”鸿蒙给 AppBar 设了哪些隐形门槛先说说背景。我手上的项目是从 Android/iOS 双端版本迁移到鸿蒙 NEXT 的。迁移本身走的是 Flutter 官方的 OpenHarmony 适配分支代码层面基本能做到“一份代码多处运行”。但真机一跑问题立刻浮出水面应用顶部那条默认的 AppBar 看起来“很 Android”完全没有鸿蒙原生应用那种轻量、克制、信息密度高的味道。很多人觉得跨平台就是“同一套 UI 到处长一个样”但在鸿蒙上这个逻辑要打个问号。鸿蒙 NEXT 的设计语言强调“沉浸式”和“分层”状态栏区域往往与应用内容融为一体顶部导航栏高度更紧凑返回手势和侧滑交互优先级极高系统字体和字重体系也跟 Material Design 有明显差异。如果你直接使用 Flutter 默认的 Scaffold AppBar出来的效果就是——标题偏大、留白过多、返回按钮样式生硬、状态栏区域颜色突兀。这就引出第一个核心判断鸿蒙适配不能只停留在“能编译、能跑、不崩溃”的层面交互习惯和视觉语言同样需要适配。我当时的应对思路是放弃系统自带 AppBar 的默认形态基于 Flutter 的 PreferredSizeWidget 和 Stack 机制重新做一个自定义的顶部导航组件就叫它 AppTopBar在保留 Flutter 跨平台能力的同时向鸿蒙原生的视觉与交互习惯靠拢。1.2 三条设计主线沉浸、紧凑、跟随系统定下自定义路线后我梳理了三条设计主线后续所有实现都围绕它们展开。第一条是“沉浸式状态栏”。鸿蒙应用普遍把背景色延伸到状态栏区域让页面顶部的颜色成为一个整体。Flutter 里对应的是SystemUiOverlayStyle和AnnotatedRegion还有鸿蒙适配分支里提供的状态栏高度读取能力。只有把状态栏高度准确算出来背景色才能铺对位置不然就会出现一条明显的“白边”或者“黑边”。第二条是“紧凑的信息密度”。Material 规范的 AppBar 默认高度是 56dp 或 64dp但在鸿蒙上顶部导航的视觉重量可以更轻我最终采用的高度是 44dp 加上状态栏高度。这个数据不是拍脑袋定的而是在鸿蒙设计规范里找到的推荐导航栏高度基准并且结合了实际真机对比效果。第三条是“跟随系统的手势交互”。鸿蒙对侧滑返回的支持力度很大页面切换动画也更强调“跟手”。自定义 AppBar 之后返回按钮的布局要预留足够的热区同时不能干扰系统侧滑手势的识别区域。这一点做到位了用户才会觉得“这个应用是鸿蒙原生开发的”而不是“一个套壳 Flutter 应用”。提示这里说的“鸿蒙原生应用”的观感是一个体验目标。Flutter 跑在鸿蒙上底层渲染走的是自绘引擎但交互和视觉是可以通过自定义组件来对齐的。1.3 为什么不用第三方 AppBar 库老实说我也查过 pub.dev 上几款热门的 AppBar 增强库比如sliver_app_bar相关的扩展、collapsible_app_bar之类的。它们功能确实强大折叠效果、滚动变色、渐变标题一应俱全但在鸿蒙这个场景下我最后还是放弃了原因有三个。第一这些库大多深度依赖 Material 设计体系自带的样式、间距、状态栏处理都是按 Android/iOS 习惯来的鸿蒙 NEXT 上很容易出现“功能没问题但审美不对味”的尴尬。第二第三方库为了支持各种滚动场景内部加了很多 Listener 和 ScrollController 的逻辑在鸿蒙适配分支上偶尔会触发性能问题折叠动画掉帧。第三也是最重要的——这些库的可定制性越高侵入性越强一旦鸿蒙适配分支的 API 有变动升级 Flutter 版本时这些库很可能成为阻塞项。自己写的组件出现问题 10 分钟就能定位用别人的库出了问题先得翻源码。所以最终方案是组件自研逻辑极简只保留必要的功能把剩余空间留给设计。2. 核心细节解析与实操要点把高度、状态栏和字体吃透2.1 状态栏高度计算——鸿蒙和 Android/iOS 不一样的地方这是整个自定义 AppBar 过程中最容易被忽视、也最容易摔跟头的地方。在 Android 上你可以通过MediaQuery.padding.top拿到状态栏高度在 iOS 上刘海屏的安全区高度也能从MediaQuery.padding.top里读到。但在鸿蒙 NEXT 适配分支上这个值的语义需要特别留意。我实测过几台鸿蒙设备MediaQuery的padding.top和viewPadding.top在部分场景下会不一致而且和页面是否开启沉浸式布局有关。如果页面没有设置沉浸式padding.top返回的可能只是安全区高度不包含状态栏全部高度一旦你想让背景色延伸到最顶部就必须额外处理。我的做法是封装一个StatusBarUtil优先读取鸿蒙适配分支提供的系统能力接口拿不到再回退到MediaQuery代码示例状态栏高度获取的降级策略class StatusBarUtil { static double getStatusBarHeight(BuildContext context) { // 鸿蒙适配分支优先走系统接口拿到的值更可靠 if (PlatformUtils.isHarmonyOS) { final harmonyHeight HarmonyOsStatusBar.height; if (harmonyHeight 0) return harmonyHeight; } // 回退到 MediaQuery final topPadding MediaQuery.paddingOf(context).top; return topPadding; } }这里有个细节我调了很久鸿蒙设备上如果开启了“应用内沉浸式布局”状态栏背景会变得透明或半透明padding.top返回的值取决于页面层级。所以不要在任何地方硬编码 24、44、48 这类数字而是每次进入页面时动态读取。也别把一次的读取结果缓存成静态变量因为用户可能从横屏切回竖屏、可能会有折叠屏设备状态栏高度是可能变化的。2.2 AppBar 高度与整体结构44dp 的取舍逻辑我在前面提到最终选了 44dp 作为导航栏主体高度这里详细说说计算过程。鸿蒙的导航栏设计基准比 Material 更紧凑。Material 规范中AppBar的toolbarHeight默认是 56dp带文本时为 64dp而鸿蒙的顶部导航建议高度更接近 44dp~48dp 这个区间。我的实际选择是 44dp理由如下44dp 在视觉上与鸿蒙系统应用“设置”“日历”等内置应用的导航栏更接近如果标题栏用大标题样式类似 iOS 的大标题44dp 会显得拥挤但鸿蒙的应用内导航普遍不强调大标题而是用清晰的中号字体44dp 配合 16dp 左右的安全区水平间距整体视觉重量轻屏幕上内容信息占比更高。整个自定义组件的结构是这样的代码示例AppTopBar 的基本结构class AppTopBar extends StatelessWidget implements PreferredSizeWidget { final String title; final Color background; final ListWidget actions; final VoidCallback? onBack; final bool automaticallyImplyLeading; const AppTopBar({ Key? key, required this.title, this.background Colors.white, this.actions const [], this.onBack, this.automaticallyImplyLeading true, }) : super(key: key); override Widget build(BuildContext context) { final statusBarHeight StatusBarUtil.getStatusBarHeight(context); return Container( color: background, padding: EdgeInsets.only(top: statusBarHeight), height: statusBarHeight 44, child: Row( children: [ if (automaticallyImplyLeading) _buildBackButton(context), Expanded(child: _buildTitle(context)), ...actions, ], ), ); } override Size get preferredSize Size.fromHeight(statusBarHeight 44); }其中preferredSize必须在 build 里同步计算因为它决定了 Scaffold 给 AppBar 分配的空间。这里有个容易踩的坑有些开发者会把preferredSize写死成Size.fromHeight(56)但自定义组件实际渲染高度是 44 加状态栏高度结果底部溢出或留白。自定义 PreferredSizeWidget 时preferredSize 必须和 build 里实际渲染的尺寸严格一致不然页面上就会出现奇怪的布局错位。2.3 字体、字重与图标细节决定“鸿蒙味”高度定了之后接下来是文字和图标细节。在鸿蒙设计语言里顶部导航标题通常采用中等偏小的字号大约在 16fp~17fp字重倾向于 Medium 或 Regular。Material 的标题默认是 20sp放在 44dp 的栏里明显偏大、偏重这也是很多人觉得 Flutter AppBar“太粗犷”的原因之一。我在自研组件里把默认字号改成了 17字重设为FontWeight.w500颜色使用高对比度的#1A1A1A或跟随主题。另一个细节是返回按钮。Flutter 自带BackButton或Icon(Icons.arrow_back)是 Material 风格的箭头鸿蒙系统应用更常使用一套“返回箭头 特定间距”的组合视觉上更轻盈。我在鸿蒙分支上优先使用系统图标资源拿不到才回退到 Material Icons。注意返回按钮的点击热区至少要 44dp x 44dp这和鸿蒙无障碍交互的最小点击范围要求是一致的。标题对齐也有讲究。普通页面标题左对齐但如果是首页或有底部 Tab 的页面标题往往居中。自研组件里我加了一个centerTitle参数默认 false左对齐在首页场景手动设为 true。这个看似简单的参数实际上对“鸿蒙味”的影响很大。2.4 安全区与圆角屏挖孔、刘海、手势条的水位问题鸿蒙设备形态很多从直板手机到折叠屏都有。除了顶部状态栏底部还有手势条区域。AppBar 位于顶部受挖孔和刘海影响最大。我的处理思路是背景尽可能延伸关键内容避开安全区。具体做法是将整个Container的背景色铺满从屏幕顶部到导航栏底部的区域包括状态栏。返回按钮、标题、操作按钮都放在安全区以内通过MediaQuery.paddingOf(context).top 44的高度来约束内容布局区域。这样就实现了“背景沉浸、内容安全”。折叠屏场景需要注意外屏和内屏的切换会导致preferredSize重新计算如果你的 App 没有处理好切屏后 AppBar 高度会闪跳。解决方案是给PreferredSizeWidget的preferredSize增加一个监听或者在页面didChangeMetrics时强制重建 Scaffold。这个后面在问题排查部分再展开。3. 实操过程与核心环节实现做一个有渐变动画的 AppTopBar3.1 滚动渐变色从透明到纯色核心是 Listenable顶部导航最常用的“美学”技巧就是滚动渐变了。常见效果是页面滚到顶部时导航栏是透明的向下滚动后逐渐变成白色或毛玻璃色。用 Flutter 实现这个效果核心就是监听滚动位置然后驱动颜色渐变。我的做法是借助ScrollController加一个AnimationController。不引入第三方库逻辑也非常简单代码示例滚动渐变 AppBar 实现class GradientAppBar extends StatefulWidget { final ScrollController controller; final String title; final Color baseColor; final double stopOpacityOffset; // 滚动多少距离后完全变为不透明 const GradientAppBar({ Key? key, required this.controller, required this.title, this.baseColor Colors.white, this.stopOpacityOffset 120, }) : super(key: key); override StateGradientAppBar createState() _GradientAppBarState(); } class _GradientAppBarState extends StateGradientAppBar with SingleTickerProviderStateMixin { late final AnimationController _animationController; late final Animationdouble _opacityAnimation; override void initState() { super.initState(); _animationController AnimationController( vsync: this, duration: const Duration(milliseconds: 60), ); _opacityAnimation Tweendouble(begin: 0, end: 1).animate( CurvedAnimation(parent: _animationController, curve: Curves.easeOut), ); widget.controller.addListener(_onScroll); } void _onScroll() { final offset widget.controller.offset; final progress (offset / widget.stopOpacityOffset).clamp(0.0, 1.0); _animationController.value progress; } override Widget build(BuildContext context) { return AnimatedBuilder( animation: _animationController, builder: (context, child) { return AppTopBar( title: widget.title, background: widget.baseColor.withOpacity(_opacityAnimation.value), ); }, ); } }这里有几个值得注意的地方第一动画时长不要拉太长。滚动距离超过stopOpacityOffset后颜色就是纯色了60ms 左右的过渡时间足够平滑又不会让用户觉得“肉”。第二AnimationController直接跟随滚动位置而不是在触发条件后播放动画。这样做的好处是“跟手”用户滚到一半停下导航栏的颜色就停在相应的透明度上。第三滚动监听的消耗问题。ScrollController的监听在滚动时会高频触发如果不加节流性能上有压力。但实测下来只是更新一个 double 值并驱动一个 AnimatedBuilder开销很小目前没有遇到卡顿。如果你的页面结构复杂可以在_onScroll里做一帧去重判断offset变化超过 0.1 才更新。3.2 标题切换与折叠渐隐AppBar 在页面中的升降级有些页面的结构是“大标题 → 小标题”的转换。典型场景是个人中心页面顶部一开始是大的页面标题随滚动逐渐缩小、变淡最终变成 AppBar 上的小标题。鸿蒙很多系统应用都有这种交互。实现在思路上跟渐变 AppBar 是同一个套路只是要多监听一个参数。我把标题的字号、字重、透明度都绑定到滚动进度上。代码示例大标题渐变为小标题的关键片段final titleScale 1.0 - progress * 0.25; // 从 1.0 缩到 0.75 final titleFontSize 26 * titleScale; final titleOpacity 1.0 - progress * 0.6;这里的progress同样是滚动偏移量与目标距离的比值。大标题到小标题的变化不需要完全线性实测用Curves.easeOutCubic会更自然因为滚动前期标题变化不明显后期快速切换到小标题视觉重心更稳。这个效果有一个容易踩的坑不要在大标题和小标题之间设置两个不同的 Widget 然后做交叉渐变替换。因为两个 Widget 的尺寸不同它们在 Stack 中的位置会跳变不管怎么插值都不自然。更好的做法是始终保持一个 Widget只调整它的fontSize、fontWeight和opacity。这样过渡是连续的。3.3 Toolbar 操作区自定义动作按钮的布局策略导航栏右侧的操作区也花了不少心思。Material 的actions默认是一个 Row间距和边距都偏大。在鸿蒙上操作按钮更适合紧凑排列并且要控制数量。顶部导航不是放按钮的仓库超过 3 个操作按钮就会出现视觉噪音。我做的约束是右侧最多放 2 个图标按钮 1 个文字按钮。图标按钮尺寸固定在 32dp点击热区 44dp间距 12dp。这样的密度在鸿蒙设备上看起来最清爽。另外在按钮点击的视觉反馈上Material 的IconButton默认有圆形的 InkWell 水波纹鸿蒙系统应用的按钮反馈更柔和。我在自研组件里用InkResponse并调整了borderRadius和高亮颜色实测观感更接近原生。3.4 导航栏阴影与分割线该有的边界感不能省顶部导航不一定要跟页面内容完全“融为一体”。当页面内容滚动到导航栏下方时如果没有阴影或分割线内容的文字、卡片会“顶”到导航栏区域产生视觉重叠的模糊感。这版组件里我把视觉边界做成了可选能力默认开启一条 0.5px 的分割线Divider高度 0.5颜色#E5E5E5滚动时才显示同时还支持阴影模式阴影的显隐同样绑定滚动进度。这里有个细节值得分享分割线不要用Container(height: 1)在部分鸿蒙设备的像素密度下一条 1px 的线会显得过粗过脏用 0.5 逻辑像素的线在多数设备上正好等于物理像素的 1px 或 2px锐利又克制。3.5 多 Tab 场景下的 AppBar 联动TabBar 嵌入还是独立做资讯类或列表类页面时AppBar 下面经常会带一个 TabBar。Flutter 自带的AppBar.bottom可以放 TabBar但默认样式没法做到鸿蒙的“紧凑 可滑动选中态”质感。我把场景拆成两种处理如果 Tab 数量少不超过 4 个且标题短直接用PreferredSize把 TabBar 塞进 AppTopBar 的 bottom保持导航栏与 Tab 之间无间距如果 Tab 数量多或标题长把 TabBar 独立放在页面 Body 的顶部跟随滚动吸顶。第二种方案的吸顶效果用CustomScrollView的SliverPersistentHeader实现pinned: true。这种做法的好处是 TabBar 吸顶时视觉连贯而且滚动性能比嵌套NestedScrollView更好。4. 常见问题与排查技巧实录鸿蒙适配路上的 AppBar 疑难杂症4.1 状态栏高度读取不准这是我最先遇到、也最折磨人的问题。现象是某些页面 AppBar 背景没有铺满状态栏顶部留了一条白边在部分设备上则是反过来背景过度延伸导致状态栏文字看不清。排查后发现问题出在“页面级的沉浸式设置”。鸿蒙适配分支下如果页面设置的是普通模式而不是沉浸式布局MediaQuery.paddingOf(context).top的值可能只包含安全区不包含状态栏的完整高度。这时如果拿这个值去做背景延伸就会出现“差一点”的偏差。解决方案在页面级优先调用鸿蒙分支提供的沉浸式布局接口让应用背景全屏延伸状态栏高度通过封装好的StatusBarUtil获取如果发现页面模式下数值异常主动切换到系统接口读取每次拿到值后打日志在真机上对照系统设置里的状态栏高度验证。4.2 Flutter Navigator 切换页面后AppBar 状态丢失AppTopBar 本质是一个 Widget它的状态会随着页面生命周期变化。有朋友问“Flutter Navigator 切换页面后状态会丢失吗”答案是分情况。如果 A 页面 push 到 B 页面A 的 State 默认被_ModalRoute保留在树里不会丢失。但是如果你在 A 页面里用了ScrollController并且没有正确释放或重建回到 A 页面时滚动位置可能被重置。这会连带导致 AppBar 的渐变状态回到初始值。我的排查思路在initState里创建 ScrollController在dispose里释放如果页面被回收重建ScrollController.initialScrollOffset可以配合PageStorageKey保存位置AppBar 的渐变状态建议完全跟随 scroll offset而不是自己保存一份“当前透明度”这样无论如何重建状态都是从滚动位置推导出来的不会出现“内容在下面导航栏却是透明”的闪跳。4.3 鸿蒙上字体渲染偏粗标题“发闷”同一个FontWeight.w500的标题在 Android 上显得清爽在鸿蒙设备上总是感觉偏粗、发闷。这个不是错觉。不同平台对字重映射不一样鸿蒙系统字体的w500实际渲染出来的视觉权重可能更高。解决办法我在鸿蒙分支上把标题字重降了一档用FontWeight.w400替代w500必要时通过TextStyle(fontVariations)微调。这里不建议全局修改只在 AppTopBar 内部处理避免影响页面其他区域的文字视觉。4.4 滚动过程中 AppBar 掉帧使用AnimatedBuilder配合ScrollController实现渐变色时大部分情况下帧率都能稳定在 90 帧以上。但如果页面里同时存在大量图片列表和复杂阴影掉帧就可能出现。掉帧的根源往往不是 AnimatedBuilder 本身而是withOpacity方法。withOpacity每次都会生成一个新的颜色对象并且在部分渲染引擎下会导致图层重绘。在鸿蒙分支上尤其明显。优化方案既然 stopOpacityOffset 范围内透明度是一个渐变过程可以改用预先计算好的颜色插值表避免每帧调用withOpacity或者直接用Color.lerp插值性能也会好一些。另外给 AppBar 的 Container 单独设一个RepaintBoundary隔离重绘区域实测掉帧问题明显减少。性能对比参考方案掉帧情况备注每帧调用 withOpacity偶发掉帧到 50~60 帧不推荐Color.lerp 插值 RepaintBoundary稳定 90~120 帧推荐预计算颜色表最稳适合变色区间固定的滚动场景4.5 AppBar 返回键与鸿蒙系统返回手势冲突鸿蒙系统本身支持左边缘侧滑返回。如果 AppBar 的返回按钮区域太靠左用户从边缘滑动时可能会误触返回按钮导致“想返回却被按钮吃掉手势”。这个问题在自定义 AppBar 时更容易出现因为返回按钮的热区往往贴着屏幕边缘。我的处理方式返回按钮的左侧保留 8dp 安全距离不贴边按钮自身热区 44dp同时用PopScope鸿蒙分支对应实现统一管理返回逻辑让系统手势优先触发页面返回按钮点击也走同一个回调。也就是说按钮只是“手动触发返回的入口”真正返回动作由路由管理统一处理这样可以避免手势和按钮事件互相干扰。4.6 沉浸式状态栏下状态栏文字颜色变浅看不清AppBar 背景是白色时没问题但一旦背景是深色图片或透明状态状态栏上的时间、电池图标颜色就可能看不清。解决思路是依据 AppBar 当前背景的亮度动态设置SystemUiOverlayStyle代码示例根据背景色动态切换状态栏图标亮度final brightness _getBackgroundBrightness(background); SystemChrome.setSystemUIOverlayStyle( brightness.isDark ? SystemUiOverlayStyle.light.copyWith( statusBarColor: Colors.transparent, ) : SystemUiOverlayStyle.dark.copyWith( statusBarColor: Colors.transparent, ), );这里的_getBackgroundBrightness可以简单比较背景色的computeLuminance()与 0.5 的关系。背景暗、亮度低就让状态栏文字变亮背景亮、亮度高就让状态栏文字变暗。5. 鸿蒙适配中的几个加分细节从“能看”到“好用”的最后一公里5.1 滚动吸顶与 TabBar 联动的完整方案如果你在做一个信息流页面顶部是导航栏下面是一级 TabTab 下面内容可以纵向滚动TabBar 需要在导航栏之下固定吸顶。这个场景很容易出现布局堆叠错乱或者滚动冲突。我最终采用CustomScrollView SliverAppBar SliverPersistentHeader的组合来彻底解决。简单来说SliverAppBar负责滚动渐变、标题折叠SliverPersistentHeader里放 TabBarpinned: true下面的列表用SliverList或SliverGrid。这样整个页面只有一个滚动视口没有嵌套滚动冲突AppBar 和 TabBar 的联动顺滑。如果你的页面里必须用ListView也可以把 TabBar 和列表一起放进CustomScrollView避免双滚动体嵌套。5.2 拆弹经验EventChannel 在鸿蒙分支上怎么用迁移过程中还涉及 Flutter 与鸿蒙原生侧的通信比如读取系统级状态栏参数这里用到了EventChannel。在 Flutter 标准 API 里MethodChannel和EventChannel的写法大家都很熟鸿蒙分支上语法基本一致但注册时用的包名或通道名要跟鸿蒙侧的ArkTS保持一致比如com.example.app/statusbar。一旦不一致调用会直接静默失败而且日志里不容易看出来排查了老半天。一个建议把所有通道名集中在一个常量类里尽量避免散落在各个模块中。鸿蒙侧和 Flutter 侧同时引用这个常量类的字符串可以显著减少这种“低级但耗时”的问题。5.3 关于“Flutter 版本升级”这件事适配过程中我原本用的是 Flutter 稳定版后来为了鸿蒙支持切换到了社区维护的鸿蒙分支。这个分支相对主线的升级节奏慢一些。如果你同时要在鸿蒙和 Android/iOS 上发布建议代码不要用任何超出分支支持范围的 API。特别是Impeller渲染引擎相关的开关。鸿蒙分支的渲染后端和主线不完全一致某些 Android 上能打开的渲染特性在鸿蒙分支上可能不生效。涉及渲染效果的优化尽量在真机上验证后再提交。5.4 双端视觉同步的一个检查组最后给一份自查清单发布前逐项过一遍能避免大部分顶部导航翻车深色/浅色模式下AppBar 背景和状态栏图标颜色是否可读横竖屏切换后AppBar 高度是否正常刷新返回手势是否被按钮吞掉多 Tab 页面滚动时TabBar 是否吸顶、AppBar 是否渐变正常大标题切换过程中文字是否出现跳变或模糊在折叠屏或小屏设备上操作区按钮是否超出安全区。我自己在实际操作中的体会是跨平台适配这件事别指望一个框架帮你把所有细节都搞定。框架解决的是“能不能跑”的问题而“跑得好不好、像不像原生”永远要靠开发者在真实设备上一轮一轮地打磨。AppBar 只是一个起点顶部导航做好了用户打开应用的第一印象就稳了一半。后面我还在继续做整个应用在鸿蒙上的沉浸式适配这套自定义组件的思路也可以沿用到底部导航、弹窗、操作面板上。迁移适配这件事没有终点但每次把一个小细节做顺都觉得这活儿值得。
返回列表