HarmonyOS鸿蒙Next中Flutter框架多设备开发指导-信息展示挂件场景

HarmonyOS鸿蒙Next中Flutter框架多设备开发指导-信息展示挂件场景

1.1 场景概述

在移动应用开发中,不同设备的屏幕形态各异,例如刘海屏、全面屏、折叠屏等,系统状态栏、导航栏、软键盘等元素亦会占据屏幕空间。直播、短视频等全屏或近全屏媒体页面上,常需在不遮挡主画面观感的前提下,叠加返回与主播信息、关注操作,以及左下角滚动提示类文案(弹幕)等「挂架」信息。若视频铺满方式与状态栏沉浸未协同,或挂架控件尺寸在宽屏上过小、在窄屏上过大,会影响可读性与点击。本文将详细介绍本示例中沉浸式视频区域计算、左上角挂架与左下角弹幕动画的实现方式。

1.1.1 使用场景

用户在全屏播放场景下需要一键返回、查看头像与昵称并切换关注状态,同时左下角周期性出现示例弹幕文案以验证叠层与动画。下面是不同横向断点下的界面示意。

横向断点 sm md lg xl
展示逻辑 返回钮约 28×28;头像直径约 24;昵称与按钮字号约 12;关注按钮内边距约 10×6、圆角 14;左下弹幕容器宽 min(安全区窗宽×0.6, 260)(逻辑像素) 返回钮约 32×32;头像约 28;字号约 14;关注内边距约 12×8、圆角 16;弹幕容器宽同上式 返回钮约 36×36;头像约 32;字号约 16;关注内边距约 14×10、圆角 18;弹幕容器宽同上式 返回钮约 36×36;头像约 32;字号约 16;关注内边距约 14×10、圆角 18;弹幕容器宽同上式
展示布局 sm展示图 md展示图 lg展示图 xl展示图

1.1.2 常见问题

全屏媒体上的信息挂架若未统筹,容易出现以下问题:

  • 视频裁切或留白与预期不符,横竖屏切换后主体偏移
  • 状态栏区域与叠层控件重叠,返回或关注不易点中
  • 控件尺寸固定,大屏上过小、小屏上拥挤

1.1.3 多设备适配

  • 适配点 1:使用 AdaptiveImmersion.getInstance().getImmersionInfo,传入视频自然尺寸(示例为 1920×1080)与安全区 frame 及 insets.top,可得到 videoSizevideoPositionisStatusBarImmersive 等;本文件 Video 仍以 width/height ‘100%’、resizeMode=“cover” 铺满根容器,videoSize / videoPosition 的计算结果在源码中未再绑定到 Video 的样式(仅 isStatusBarImmersive 等用于后续逻辑);挂架为更高 zIndex 的绝对定位层。

图 1-1手机竖屏下全屏视频与左上挂架、左下弹幕。

手机竖屏图

图 1-2手机横屏下同一套挂架与弹幕与画面的关系。

手机横屏图

  • 适配点 2useFocusEffect 依赖 isStatusBarImmersive,与沉浸式状态栏建议配合。

图 2-1md 断点下挂架尺寸与弹幕区域。

md断点图

图 2-2lg 断点下更大头像与字号。

lg断点图

图 2-3PC / 全屏窗口下整页效果。

PC全屏窗口图

1.2 开发指导

1.2.1 Flutter开发

1.2.1.1 关键能力

1、安全区避让布局

信息展示挂件采用 Stack 层叠布局,将背景层(视频/图片)与前景 UI 元素分离。整体布局通过 SafeArea 包裹,背景层和前景 UI 元素均在安全区域内展示,确保在竖屏和横屏模式下均能正确避让系统状态栏和导航栏,不被系统 UI 遮挡。

2、响应式断点适配

采用四级断点响应式设计,根据屏幕宽度自动调整挂件中各 UI 元素的尺寸和间距:

断点 屏幕宽度范围 说明
base 0 - 600px 手机竖屏等小屏设备
sm 600 - 840px 手机横屏、小平板
md 840 - 1024px 平板设备
lg 1024px+ 大屏平板、桌面设备

1.2.1.2 指导案例

1、整体布局实现

信息展示挂件的核心是 SafeArea + Stack 层叠布局,整体包裹在 SafeArea 内,分为两层:

  • 底层:背景内容(视频、图片等),在安全区域内铺满
  • 上层:前景 UI 挂件,通过 Positioned 定位
Scaffold(
  backgroundColor: Colors.black,
  body: SafeArea(
    child: Stack(
      children: [
        // 底层:背景(安全区域内铺满)
        SizedBox.expand(
          child: FittedBox(
            fit: BoxFit.cover,
            child: /* 背景内容(视频/图片) */,
          ),
        ),
        // 上层:前景 UI 挂件
        Stack(
          children: [
            Positioned(
              left: 12, top: 12,
              child: /* 信息卡片挂件 */,
            ),
            Positioned(
              left: 12, bottom: 24,
              child: /* 其他挂件 */,
            ),
          ],
        ),
      ],
    ),
  ),
)

2、响应式断点方法

各挂件组件内部通过 _getResponsiveValue 泛型方法实现断点适配,根据 MediaQuery 获取的屏幕宽度返回对应断点的值:

T _getResponsiveValue<T>({
  required double screenWidth,
  required T base,
  required T sm,
  required T md,
  required T lg,
}) {
  if (screenWidth >= 1024) return lg;
  else if (screenWidth >= 840) return md;
  else if (screenWidth >= 600) return sm;
  else return base;
}

使用示例——对按钮尺寸、文字大小、内边距等进行响应式调整:

final screenWidth = MediaQuery.of(context).size.width;

final iconSize = _getResponsiveValue(
  screenWidth: screenWidth,
  base: 28.0, sm: 28.0, md: 32.0, lg: 36.0,
);

final textSize = _getResponsiveValue<double>(
  screenWidth: screenWidth,
  base: 12.0, sm: 12.0, md: 14.0, lg: 16.0,
);

final padding = _getResponsiveValue<EdgeInsets>(
  screenWidth: screenWidth,
  base: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
  sm: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
  md: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
  lg: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
);

3、信息卡片挂件实现

信息卡片是信息展示挂件的核心组件,采用 Row 横向排列多个元素(图片、文字、按钮等),外层用半透明圆角容器包裹:

Container(
  padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 6),
  decoration: BoxDecoration(
    color: Colors.black.withOpacity(0.3),
    borderRadius: BorderRadius.circular(18),
  ),
  child: Row(
    mainAxisSize: MainAxisSize.min,
    children: [
      // 图片元素
      ClipRRect(
        borderRadius: BorderRadius.circular(avatarSize / 2),
        child: Image.asset(imageUrl, width: avatarSize, height: avatarSize),
      ),
      const SizedBox(width: 8),
      // 文字元素
      Text(title, style: TextStyle(color: Colors.white, fontSize: textSize)),
      const SizedBox(width: 8),
      // 交互按钮(支持状态切换)
      GestureDetector(
        onTap: () => setState(() { _isActive = !_isActive; }),
        child: Container(
          padding: buttonPadding,
          decoration: BoxDecoration(
            color: _isActive
            ? Colors.white.withOpacity(0.2)
            : const Color(0xFFFF5252),
            borderRadius: BorderRadius.circular(buttonRadius),
          ),
          child: Text(_isActive ? '已关注' : '关注'),
        ),
      ),
    ],
  ),
)

1.2.1.3 示例代码

信息展示挂件的Sample示例代码地址:example,开发者可以通过该地址查看完整的视频通话示例代码,并根据自己的需求进行修改和扩展。


更多关于HarmonyOS鸿蒙Next中Flutter框架多设备开发指导-信息展示挂件场景的实战教程也可以访问 https://www.itying.com/category-92-b0.html

3 回复

更多关于HarmonyOS鸿蒙Next中Flutter框架多设备开发指导-信息展示挂件场景的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在HarmonyOS Next中,使用Flutter开发信息展示挂件时,需通过Flutter Module集成到ArkUI的Widget Extension中。利用Platform Channel实现Flutter与原生ArkUI的数据同步,并针对不同设备屏幕尺寸使用MediaQueryLayoutBuilder进行自适应布局。确保挂件刷新依赖Timer或数据推送触发重建。

信息展示挂件适配的核心是 SafeArea + Stack 层叠布局,背景层铺满安全区,前景控件通过 Positioned 定位避开状态栏和导航栏。响应式适配采用四级断点(base/sm/md/lg),通过 _getResponsiveValue 方法根据屏幕宽度动态调整图标、字号、内边距等尺寸。卡片组件用半透明圆角容器包裹头像、昵称和状态按钮,按钮支持交互状态切换。弹幕区域宽度使用 min(安全区宽×0.6, 260) 限制,确保不同屏幕下叠层信息可读且不遮挡主画面。

回到顶部