今天的专题是关于多设备适配定位的,这个场景的异常通常表现为布局异常、避让失效、帧率不正确等,这些问题一般不会导致你的应用崩溃,但会严重影响应用的体验,以下是罗列出的6大类问题及现象

问题类型异常现象
分栏不生效/异常宽屏未分栏、主页识别错误、弹窗蒙层缺失
安全区域避让失效内容被状态栏/挖孔/窗口按钮遮挡
折叠屏适配异常折痕区域未避让、DisplayFeature 缺失
DPI 缩放异常界面过大/过小、自定义 DPI 不生效
LTPO 帧率异常滑动帧率不提升、转场帧率不切换
多窗口/自由窗口异常窗口缩放布局不刷新、窗口按钮遮挡

根据问题分类,可以通过HiLog关键字快速定位:
在这里插入图片描述

二、分栏不生效/异常

分栏是平板、大屏设备的核心适配能力,绝大多数问题集中在配置加载、主页识别、弹窗适配三大场景。

2.1 分栏不生效排查方法

第 1 步,确认配置文件是否正确

文件路径 ohos/entry/src/main/resources/rawfile/split_config.json

第 2 步,搜索日志,根据关键字信息进行问题排查

hdc shell "hilog | grep -E 'SplitView|split_view|SplitViewConfig'"
日志关键字含义正常/异常
SplitView: Main page determined by config homePage: /home通过 homePage 配置识别主页正常
SplitView: Main page determined by widget.home通过 home 参数识别主页正常
SplitView: Main page determined by routes: /home通过 routes 识别主页正常
SplitView: Main page determined by initialRoute通过 initialRoute 识别主页正常
SystemChannel config parse failed: ...配置 JSON 解析失败异常
SplitViewConfig: Failed to decode placeholder icon: ...占位图标 base64 解码失败异常
SplitViewConfig: Some fullScreenPages items are not stringsfullScreenPages 配置项类型错误异常
Cannot determine main page for split screen无法识别主页(抛出 FlutterError)异常

第 3 步,分栏功能需要同时满足以下触发条件,需要依次排查

  • 逻辑宽度 > 600vp 且 逻辑高度 > 600vp
  • 宽高比 > 1.2(宽屏模式)或 宽高比 ≤ 1.2(方屏模式)
  • 对应配置项已启用(enableWideWindowSplit / enableSquareWindowSplit)

2.2 主页识别错误

出现异常现象主要为以下几类:(1)主页无法识别,分栏不工作(2)路由名为 null,无法匹配主页/全屏页(3)全屏页面不生效(4)无法识别;具体原因和解决方法可以参考下:

原因现象解决方案
Router 模式未配置 homePage主页无法识别,分栏不工作Router 模式必须填写 homePage
MaterialPageRoute 未保留 settings路由名为 null,无法匹配主页/全屏页MaterialPageRoute(settings: settings, ...)
GoRoute.name 与配置不匹配全屏页面不生效确保 GoRoute.name 与 fullScreenPages 完全一致
三元表达式判断主页无法识别使用 initialRoute + 路由表替代

关键字日志排查命令如下:

hdc shell "hilog | grep 'SplitView: Main page'"

2.3 弹窗蒙层问题

问题根源:分栏场景下,showModalBottomSheet、showMenu、showSearch 蒙层不正确,主要原因是这些API默认 useRootNavigator: false,分栏场景下需要设置为true。

代码修复:

// 分栏场景需显式设置
showModalBottomSheet(
  context: context,
  // 需要添加这一行,设置为true
  useRootNavigator: true,
  builder: (context) => SheetContent(),
);

三、安全区域避让

3.1 四种避让类型

FlutterView 会监听四种避让区域变化,搜 avoidAreaChangeCallback,正常日志按类型区分如下:

# 1. TYPE_SYSTEM:系统栏,状态栏加三键导航栏
I Flutter: avoidAreaChangeCallback, type=TYPE_SYSTEM, area={topRect: {height: 36}, bottomRect: {height: 28}, ...}
# 2. TYPE_CUTOUT:挖孔、刘海区域
I Flutter: avoidAreaChangeCallback, type=TYPE_CUTOUT, area={topRect: {height: 84}, leftRect: {width: 0}, ...}
# 3. TYPE_NAVIGATION_INDICATOR:手势导航条,底部 HOME 条
I Flutter: avoidAreaChangeCallback, type=TYPE_NAVIGATION_INDICATOR, area={bottomRect: {height: 24}, ...}
# 4. TYPE_KEYBOARD:软键盘
I Flutter: avoidAreaChangeCallback, type=TYPE_KEYBOARD, area={bottomRect: {height: 280}}

通过命令行搜索:

hdc shell "hilog | grep -E 'avoidAreaChangeCallback|avoidArea'"

如果出现以下异常日志,可根据现场进行排查下:

# FlutterView 非活跃时忽略避让变化(正常行为) 
D Flutter: <viewId> is not active. Ignoring avoid area change.

异常现象及可能原因排查梳理:

现象可能原因解决方案
避让区域始终为 0未调用 setWindowLayoutFullScreen(true)EntryAbility 中设置全屏布局
横竖屏切换后避让未更新FlutterView 未收到 avoidAreaChange检查回调注册是否成功
分屏场景避让错误使用了缓存的 padding 值用 MediaQuery.of(context).padding 实时获取
键盘弹出后避让不恢复viewInsets 未清零检查 onKeyboardAreaChange 逻辑
挖孔区域未避让未监听 TYPE_CUTOUT 或 SafeArea 顶部未生效确认全屏布局已开启,用 SafeArea(top: true)
底部内容被手势条遮挡未监听 TYPE_NAVIGATION_INDICATORSafeArea(bottom: true),切换后重读 viewPadding.bottom

四、折叠屏 DisplayFeature问题

  1. Flutter鸿蒙应用上是通过MediaQuery.of(context).displayFeatures 获取屏幕特征(挖孔、折痕等),我们通过以下日志进行过滤:
hdc shell "hilog | grep -E 'displayFeature|displayFeatures|cutoutInfo'"

通过Type类型,可以确认屏幕特性是否匹配

# type 值含义:0=UNKNOWN, 1=FOLD, 2=HINGE, 3=CUTOUT
D Flutter: device displayFeatures is : [{"bound":{...},"type":3,"state":0}]

2. 折叠状态通过如下命令行进行监听

hdc shell "hilog | grep -E 'foldStatus|Fold status|foldStatusChange'"

正常状态的日志如下,可根据实际日志进行比对

# 1=展开, 2=折叠, 3=半折叠
D Flutter: Fold status change to {"status":1} 

五、DPI 缩放问题

1. devicePixelRatio 不更新问题 是通过搜索 device pixel ratio|densityUpdate|dpiScale,进行定位的,``命令行如下:

hdc shell "hilog | grep -E 'device pixel ratio|devicePixelRatio|densityUpdate|dpiScale'"

根据日志进行问题排查

日志含义
Device pixel ratio updated: 3.0DPI 更新成功
Resetting device pixel ratio to system default重置为系统默认 DPI
Scaling device pixel ratio by factor 0.85按缩放因子调整 DPI
Error updating device pixel ratio更新失败,异常
densityUpdateCallback: customDensity=…密度变化回调

2. DPI 的问题 有3条关键命令行:

# 确认 DPI 缩放调用
hdc shell "hilog | grep -E 'displaymetrics|updateDpiScale|customDpi'"
# 路由切换时自定义 DPI 重置逻辑
hdc shell "hilog | grep -E 'customDpiActive|currentUri|setCurrentUri'"
# 窗口尺寸变化导致 DPI 异常
hdc shell "hilog | grep -E 'windowSizeChangeCallback'"

六、窗口问题

1. 窗口随尺寸变化不刷新,排查命令行如下:

hdc shell "hilog | grep -E 'windowSizeChangeCallback|windowRectChange|windowStatusChange'"
回调日志关键字作用
windowSizeChangeCallbackwindowSizeChangeCallback窗口尺寸变化(更新 DPI)
windowRectChangeCallbackwindowRectChange窗口位置变化
windowStatusChangeCallbackwindowStatusChange窗口状态变化(全屏/分屏等)

布局不刷新的常见原因:

  • 未监听 WidgetsBindingObserver.didChangeMetrics
  • 使用了缓存的 MediaQuery 值
  • 分栏激活状态未更新(_checkScreenSizeAndSetSplitScreen)

以上就是本次DFX系列的最后一篇了,这个系列总计11篇,感谢关注~

点赞+关注

关注 CPF-Flutter 社区

“AI再牛,技术不能丢

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐