尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Flutter 显示刘海(Display Cutout)与屏幕旋转集成测试:display_cutout_rotation 深度解析
Flutter 显示刘海Display Cutout与屏幕旋转集成测试display_cutout_rotation 深度解析【免费下载链接】flutterFlutter makes it easy and fast to build beautiful apps for mobile and beyond项目地址: https://gitcode.com/GitHub_Trending/flutter41/flutter本文围绕 Flutter 仓库中的 display_cutout_rotation 集成测试展开它验证 Android 设备的显示刘海cutout在竖屏/横屏旋转时能否通过MediaQuery.of(context).displayFeatures被 Dart 应用代码正确感知。读完本文你将掌握该测试的本地运行方式、devicelab 自动化调度原理、测试用例的断言逻辑以及从引擎侧DisplayFeature类型到框架侧 API 的完整数据链路。测试目标验证刘海在旋转时位置的实时更新Android 自 API 28 起在开发者选项中提供模拟刘海display cutout emulation能力API 30 起该行为稳定可用。display_cutout_rotation测试的核心场景是当设备开启模拟刘海后旋转屏幕时原本位于顶部的刘海竖屏应报告为位于左侧landscapeLeft应用侧的DisplayFeature数据必须随之正确更新。测试假设设备上已启用开发者选项com.android.internal.display.cutout.emulation.tall并在以下三种场景中断言竖屏portraitUp时存在唯一一个 cutout 类型特征且其bounds.top 0刘海贴顶横屏向左landscapeLeft时同样只有一个 cutout且bounds.left 0刘海贴左侧在同一 App 实例内从竖屏旋转到横屏特征查询结果能从顶部切换为左侧验证旋转过程中数据的动态更新。项目结构与运行方式该测试工程位于dev/integration_tests/display_cutout_rotation/是一个标准的 Flutter 集成测试应用由三部分组成lib/main.dart被测的极简 App负责把当前刘海状态以文本形式渲染出来integration_test/display_cutout_test.dart基于integration_test包的端到端测试用例pubspec.yaml依赖flutter、flutter_test、flutter_driver与integration_test均来自 SDK并设置了resolution: workspace参与仓库的 workspace 解析publish_to: none表明其为私有工程。按照 README 的说明本地运行有两种方式# 方式一在工程目录内直接运行集成测试 cd dev/integration_tests/display_cutout_rotation flutter test integration_test/display_cutout_test.dart # 方式二通过 devicelab 测试运行器执行 cd dev/devicelab dart bin/test_runner.dart test -t android_display_cutout方式二走的是 devicelab 任务体系android_display_cutout任务的真实定义在 dev/devicelab/lib/tasks/integration_tests.dart 中的createDisplayCutoutTest()。源码注释明确给出了适用前提设备必须启用开发者设置且为 Android API 30 及以上运行时通过getprop ro.build.version.sdk校验SDK 小于 30 直接判失败仅支持 Android 设备非AndroidDevice直接抛TaskResult.failure任务setup阶段执行cmd overlay enable com.android.internal.display.cutout.emulation.tall在设备上注入合成刘海Synthetic notch注释特别提示该命令会导致正在运行的 Android Activity 被重新创建tearDown阶段执行cmd overlay disable移除合成刘海避免污染后续测试。也就是说README 中假设设备已启用com.android.internal.display.cutout.emulation.tall这一前提在 CI 路径下由 devicelab 任务自动完成注入与清理本地手动运行则需自行开启。被测应用把刘海状态可视化的最小实现lib/main.dart 中只有约 50 行代码MyApp的build方法核心逻辑如下final ListDisplayFeature displayFeatures MediaQuery.of(context).displayFeatures; displayFeatures.retainWhere( (DisplayFeature feature) feature.type DisplayFeatureType.cutout, ); // ... final Rect cutout displayFeatures[0].bounds; if (cutout.top 0) { text CutoutTop; } else if (cutout.left 0) { text CutoutLeft; } else { text CutoutNeither; } return MaterialApp( debugShowCheckedModeBanner: false, home: Text(Cutout status: $text, key: Key(text)), );源码注释解释了这段对测试而言并非必需的逻辑存在的目的它在人工视觉调试或观看远端设备录像时很有用——屏幕上直接显示CutoutTop/CutoutLeft/CutoutNone/CutoutMany/CutoutNeither之一的状态文本同时Text组件还携带一个与内容一致的Key。测试代码正是依赖这个Text元素通过find.byType(Text)定位BuildContext进而读取MediaQuery数据因此注释强调Tests assume there is some text element displayed。测试用例详解旋转、轮询与断言integration_test/display_cutout_test.dart 使用IntegrationTestWidgetsFlutterBinding.ensureInitialized()初始化后包含三个testWidgets用例与一个tearDown1. 竖屏时刘海在顶部await setOrientationAndWaitUntilRotation(tester, DeviceOrientation.portraitUp); await tester.pumpWidget(const MyApp()); final BuildContext context tester.element(find.byType(Text)); final IterableDisplayFeature displayFeatures getCutouts(tester, context); expect(displayFeatures.length, 1, reason: Single cutout display feature expected); expect(displayFeatures.first.bounds.top, 0, ...);断言的reason写得很有工程经验如果top不为 0提示测试设备上是否已有真实摄像头刘海或 window inset——即合成刘海与真机硬件刘海可能叠加导致断言失败时能快速定位原因。2. 横屏向左时刘海在左侧与用例 1 对称旋转至DeviceOrientation.landscapeLeft后断言displayFeatures.first.bounds.left 0。3. 旋转过程中刘海位置动态更新这是唯一不重新pumpWidget新实例、而是复用同一MyApp实例的用例先验证竖屏下top 0再调用setOrientationAndWaitUntilRotation切到landscapeLeft并重新pumpWidget然后重新获取BuildContexttester.element(find.byType(Text))再次查询再断言left 0。它验证的关键点是旋转后MediaQuery.displayFeatures的数据不是陈旧的会随窗口布局变化被框架刷新。旋转等待与特征过滤的两个辅助函数旋转等待函数体现了对底层异步链路的理解源码注释写道Rotations have an async communication to engine which then has an async communication to the android operating system——Dart 层发起旋转请求后经由引擎与 Android 系统两次异步通信才能完成因此需要轮询Futurevoid setOrientationAndWaitUntilRotation( WidgetTester tester, DeviceOrientation orientation, ) async { await SystemChrome.setPreferredOrientations(DeviceOrientation[orientation]); // 将 DeviceOrientation 映射为期望的 Orientationportrait/landscape while (true) { final BuildContext context tester.element(find.byType(Text)); if (context.mounted expectedOrientation MediaQuery.of(context).orientation) { break; } await tester.pumpAndSettle(); } }getCutouts则封装了对displayFeatures的过滤逻辑只保留feature.type DisplayFeatureType.cutout的特征排除fold、hinge等其他类型IterableDisplayFeature getCutouts(WidgetTester tester, BuildContext context) { final ListDisplayFeature displayFeatures MediaQuery.of(context).displayFeatures; return displayFeatures.where( (DisplayFeature feature) feature.type DisplayFeatureType.cutout, ); }tearDown中调用SystemChrome.setPreferredOrientations(DeviceOrientation[])恢复设备默认方向注释说明这是为了避免测试污染test pollution确保后续用例或同一设备上的其他任务不受方向设置影响。底层原理DisplayFeature 数据从 Android 到 Dart 的链路从源码结构看DisplayFeature在本仓库中是一条贯穿 Android 嵌入层、引擎 Dart 层的数据模型Dart 引擎侧engine/src/flutter/lib/ui/platform_dispatcher.dart 定义了DisplayFeature类文档注释明确 This is populated only on Android包含三个字段bounds以逻辑像素表示、被硬件特征占据的区域在双屏设备上坐标系从左屏或上屏的左上角 (0,0) 起算横跨两块屏幕及中间视觉空间typeDisplayFeatureType其中hinge与cutout会遮挡显示区域fold不会state折叠/铰链的姿态如postureFlat、postureHalfOpened而对cutout类型恒为DisplayFeatureState.unknown——构造函数中甚至有断言强制这一约束!identical(type, cutout) || identical(state, unknown)Android 引擎侧engine/src/flutter/shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java 中存在对应的 JavaDisplayFeature类与DisplayFeatureType枚举注释说明其基于androidx.window.layout.DisplayFeature并增加了对 cutout 的支持其中CUTOUT(3)明确对应android.view.DisplayCutout即 Android 系统对摄像头/传感器开孔区域的原生抽象。这解释了测试断言的坐标系语义bounds.top 0表示切出区域紧贴窗口顶部bounds.left 0表示紧贴左侧——正是合成刘海在竖屏/横屏下的预期位置。关键前提与限制结合测试源码与 devicelab 任务实现可以归纳出运行和解读该测试的几个约束约束来源说明仅 Androidintegration_tests.dartdevice is! AndroidDevice时任务直接失败Android API 30integration_tests.dart开发者设置项在 API 28 加入、行为在 API 30 才完整需开发者选项 合成刘海README手动运行时须先启用com.android.internal.display.cutout.emulation.talldevicelab 路径由setup自动注入断言对真实硬件刘海敏感display_cutout_test.dart真机自带的摄像头开孔会叠加在合成刘海之上导致top/left 0断言或恰好一个 cutout断言失败断言 reason 中已给出排查提示cutout的state恒为 unknownplatform_dispatcher.dart引擎层构造断言保证姿态信息仅对折叠类特征有意义小结display_cutout_rotation用不到 200 行代码构建了一个高价值的端到端回归场景通过 devicelab 注入合成刘海、通过SystemChrome.setPreferredOrientations 轮询模拟真实旋转、再通过MediaQuery.displayFeatures断言 cutout 的bounds随方向正确迁移。它既验证了 Android 嵌入层到引擎再到框架的DisplayFeature数据通路也覆盖了旋转这类跨异步边界的时序场景是理解 Flutter 如何感知折叠屏/刘海等硬件显示特征的一个精确而完整的入口。【免费下载链接】flutterFlutter makes it easy and fast to build beautiful apps for mobile and beyond项目地址: https://gitcode.com/GitHub_Trending/flutter41/flutter创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

Ansible 测试实战:用 ansible-test 运行 Sanity、单元与集成测试

Ansible 测试实战:用 ansible-test 运行 Sanity、单元与集成测试

Ansible 测试实战:用 ansible-test 运行 Sanity、单元与集成测试 【免费下载链接】ansible Ansible is a radically simple IT automation platform that makes your applications and systems easier to deploy and maintain. Automate everything from code deployment to ne…

📅 2026/10/15 3:01:02
Strapi OpenAPI 文档组装器开发指南:从叶子 Assembler 到复合 Assembler

Strapi OpenAPI 文档组装器开发指南:从叶子 Assembler 到复合 Assembler

Strapi OpenAPI 文档组装器开发指南:从叶子 Assembler 到复合 Assembler 【免费下载链接】strapi 🚀 Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable, and developer-first. 项目地址: https…

📅 2026/10/9 16:59:41
天空过曝、暗部死黑?3 步讲透 HDR 高动态范围成像

天空过曝、暗部死黑?3 步讲透 HDR 高动态范围成像

天空过曝、暗部死黑?3 步讲透 HDR 高动态范围成像 【免费下载链接】awesome-computer-vision A curated list of awesome computer vision resources 项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-computer-vision 刚拍完一张照片,…

📅 2026/10/8 3:30:06
MORE NEWS

更多资讯

📰

URFormer:关系词表与专家路由实现异构图零样本迁移

做异构图模型的同学大概都有过这种体验:业务方甩过来一张新图,schema 里躺着二十几种节点类型、上百种边语义,你手里的模型只认得训练时见过的那几种关系,于是又是一轮重写特征、重训 embedding、重调参。一个模型,任意…

📰

百亿级量化机构高性能分布式存储:场景、技术栈与落地实践

“高性能分布式存储”这个词一旦出现在量化私募的招聘标题里,味道就和互联网大厂的基础设施岗完全不同了。互联网存储团队服务的是海量用户请求,核心矛盾是并发、成本和横向扩展;百亿级量化机构养一支存储团队,服务的是几十到几百…

📰

OpenMontage:用代码批量生成视频的开放编排框架

1. 从“OpenMontage”这个名字说起:它到底想解决什么问题第一次看到“OpenMontage”这个词,我脑子里蹦出来的第一反应是“开放式的蒙太奇”。蒙太奇是影视剪辑里最核心的手法之一——把不同来源、不同时间、不同空间的镜头拼接在一起,产生新的…

📰

Win7 WDM驱动内存映射实验:物理页分配与IRP读写实现

简介:这是一份面向Windows驱动开发初学者与内核安全研究者的Win7内存读写驱动实践项目,聚焦Ring 0级物理内存直接访问能力的实现与调试。资源提供完整可编译的WDM模型驱动工程,涵盖驱动初始化、IRP请求处理、连续内存分配(MmAlloc…

📰

基于Cloudflare Workers的AI Agent工程化模板:pnpm依赖管理与边缘部署实践

1. 从“cloudflare-os”这个名字说起:它到底想解决什么问题第一次看到cloudflare-os这个仓库名,我下意识以为 Cloudflare 又出了什么边缘操作系统。点进去翻了翻目录结构和提交记录才反应过来,这其实是一个把 Cloudflare Workers 当作“运行时…

📰

AI+BI如何优化企业实时决策与监控系统

1. 为什么AIBI正在重塑企业决策模式?在零售门店的凌晨盘点时段,店长手机突然弹出预警:某畅销商品库存仅剩3天销量。与此同时,系统自动生成补货建议单,并同步调整了周边门店的调拨方案。这种实时决策场景,正…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬