欢迎加入开源鸿蒙PC社区:
https://harmonypc.csdn.net/

atomgit仓库地址: https://atomgit.com/gcw_7DJ1SfsY/PCsuofang
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在开发鸿蒙PC端应用时,窗口配置是一个常见但容易出错的环节。本文将详细记录在实际项目中遇到的窗口配置问题,包括配置文件错误、API调用错误等,并提供完整的解决方案。

问题背景

在开发一个鸿蒙PC端应用时,我们需要对窗口行为进行控制,具体需求是实现窗口不可缩放的功能。在尝试配置过程中,遇到了一系列构建错误,包括配置文件验证失败和编译错误。

遇到的问题

问题一:module.json5配置文件验证失败

第一次构建时,遇到了以下错误:

> hvigor ERROR: Failed :entry:default@PreBuild... 
> hvigor ERROR: 00303038 Configuration Error 
Error Message: Schema validate failed, at file: entry/src/main/module.json5

Error: Property 'windowResizable' does not exist
Error: Property 'windowMode' does not exist

原始配置文件中使用了以下无效属性:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "windowResizable": true,
        "windowMode": "floating"
      }
    ]
  }
}

问题二:API调用不存在

修复配置文件后,又遇到编译错误:

> hvigor ERROR: ArkTS Compiler Error
Error: Property 'setWindowResizable' does not exist on type 'Window'
Error: Property 'setWindowMode' does not exist on type 'Window'
Error: Property 'WindowMode' does not exist on type 'typeof window'
Error: Property 'setWindowMinSize' does not exist on type 'Window'
Error: Property 'setWindowPreferredSize' does not exist on type 'Window'

原始代码中尝试通过API动态设置窗口属性:

mainWindow.setWindowResizable(true);
mainWindow.setWindowMode(window.WindowMode.FLOATING);
mainWindow.setWindowMinSize(400, 300);
mainWindow.setWindowPreferredSize(800, 600);

问题三:supportWindowMode值错误

在尝试修复时,使用了错误的窗口模式值:

Error: must be equal to one of the allowed values
allowedValues: ['fullscreen', 'split', 'floating']

配置中使用了 "fixed" 这个不存在的值:

"supportWindowMode": ["fullscreen", "fixed"]

问题分析

鸿蒙窗口配置机制

在鸿蒙系统中,窗口的行为控制主要通过配置文件实现,而不是通过代码动态设置。这是鸿蒙与传统桌面应用开发的一个重要区别。

配置优先原则:窗口的基本能力(是否可缩放、支持的窗口模式等)在应用安装时就已经确定,通过 module.json5 配置文件声明。这样做的好处是:

  1. 系统可以在应用启动前就知道窗口特性,提前做好资源分配
  2. 避免运行时频繁改变窗口模式带来的性能开销
  3. 提供一致的用户体验,防止应用随意改变窗口行为

配置文件结构

module.json5 是鸿蒙应用的模块配置文件,其中 abilities 数组定义了应用的能力(Ability)。每个Ability可以配置以下窗口相关属性:

属性名 类型 说明
supportWindowMode string[] 支持的窗口模式,可选值:fullscreen、split、floating
minWindowWidth number 最小窗口宽度(vp)
minWindowHeight number 最小窗口高度(vp)
maxWindowWidth number 最大窗口宽度(vp)
maxWindowHeight number 最大窗口高度(vp)
maxWindowRatio number 最大窗口宽高比
minWindowRatio number 最小窗口宽高比

窗口模式详解

鸿蒙PC端支持三种窗口模式:

  1. fullscreen(全屏模式)

    • 窗口占据整个屏幕
    • 不显示窗口边框和控制按钮
    • 用户无法调整窗口大小
    • 适用于沉浸式体验的应用,如游戏、视频播放器
  2. split(分屏模式)

    • 窗口可以与其他应用分屏显示
    • 支持拖拽调整分屏比例
    • 适用于需要多任务并行的场景
  3. floating(浮动窗口模式)

    • 窗口以独立浮动窗口形式显示
    • 显示完整的窗口边框和控制按钮(最小化、最大化、关闭)
    • 用户可以自由拖拽调整窗口位置和大小
    • 适用于常规桌面应用

解决方案

核心代码一:正确的配置文件设置

要实现窗口不可缩放,需要在 module.json5 中只声明支持全屏模式:

{
  "module": {
    "name": "entry",
    "type": "entry",
    "description": "$string:module_desc",
    "mainElement": "EntryAbility",
    "deviceTypes": [
      "2in1"
    ],
    "deliveryWithInstall": true,
    "installationFree": false,
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets",
        "description": "$string:EntryAbility_desc",
        "icon": "$media:layered_image",
        "label": "$string:EntryAbility_label",
        "startWindowIcon": "$media:startIcon",
        "startWindowBackground": "$color:start_window_background",
        "exported": true,
        "skills": [
          {
            "entities": [
              "entity.system.home"
            ],
            "actions": [
              "ohos.want.action.home"
            ]
          }
        ],
        // 只支持全屏模式,窗口不可缩放
        "supportWindowMode": ["fullscreen"]
      }
    ]
  }
}

关键点说明

  • deviceTypes: ["2in1"] 表示这是一个PC端应用(2in1设备)
  • supportWindowMode: ["fullscreen"] 只声明支持全屏模式,系统不会显示窗口控制按钮
  • 不需要设置 minWindowWidthminWindowHeight,因为全屏模式下这些配置无效

核心代码二:支持窗口缩放的配置

如果需要支持窗口缩放,应该配置浮动窗口模式:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        // 支持全屏和浮动两种模式
        "supportWindowMode": ["fullscreen", "floating"],
        // 设置窗口最小尺寸限制
        "minWindowWidth": 400,
        "minWindowHeight": 300,
        // 可选:设置窗口最大尺寸限制
        "maxWindowWidth": 1920,
        "maxWindowHeight": 1080
      }
    ]
  }
}

关键点说明

  • supportWindowMode 数组可以包含多个值,表示应用支持多种窗口模式
  • 包含 "floating" 时,窗口会显示边框和控制按钮,用户可以缩放窗口
  • minWindowWidthminWindowHeight 防止用户将窗口缩放到过小导致UI变形
  • 尺寸单位是 vp(虚拟像素),会根据屏幕密度自动适配

核心代码三:EntryAbility中的正确处理方式

在代码中,不应该尝试调用不存在的窗口设置API。正确的做法是:

import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';

const DOMAIN = 0x0000;

export default class EntryAbility extends UIAbility {
  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    try {
      this.context.getApplicationContext().setColorMode(
        ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET
      );
    } catch (err) {
      hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', 
        JSON.stringify(err));
    }
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate');
  }

  onDestroy(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy');
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');

    // 窗口配置说明:
    // 在鸿蒙中,窗口的缩放能力和模式通过 module.json5 配置
    // - supportWindowMode: ["fullscreen"] 只支持全屏,窗口不可缩放
    // - supportWindowMode: ["fullscreen", "floating"] 支持浮动窗口,可缩放

    // 如需动态调整窗口大小,可使用 resize() 方法
    try {
      windowStage.getMainWindow((err: BusinessError, mainWindow: window.Window) => {
        if (err) {
          hilog.error(DOMAIN, 'testTag', 'Failed to get main window. Cause: %{public}s', 
            JSON.stringify(err));
          return;
        }

        // 设置窗口初始大小(仅在浮动模式下有效)
        mainWindow.resize(800, 600, (err: BusinessError) => {
          if (err) {
            hilog.error(DOMAIN, 'testTag', 'Failed to resize window. Cause: %{public}s', 
              JSON.stringify(err));
            return;
          }
          hilog.info(DOMAIN, 'testTag', 'Window size set to 800x600');
        });
      });
    } catch (e) {
      hilog.error(DOMAIN, 'testTag', 'Window configuration exception: %{public}s', 
        JSON.stringify(e));
    }

    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', 
          JSON.stringify(err));
        return;
      }
      hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');
    });
  }

  onWindowStageDestroy(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
  }

  onForeground(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground');
  }

  onBackground(): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground');
  }
}

关键点说明

  • 不要使用 setWindowResizable()setWindowMode() 等不存在的API
  • 可以使用 resize(width, height) 方法动态调整窗口大小
  • resize() 方法只在浮动窗口模式下有效,全屏模式下调用会被忽略

核心代码四:窗口尺寸限制的最佳实践

在实际项目中,合理的窗口尺寸限制可以提升用户体验:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "supportWindowMode": ["fullscreen", "floating"],
        // 最小尺寸:确保UI元素可读
        "minWindowWidth": 800,
        "minWindowHeight": 600,
        // 最大尺寸:防止在大屏幕上窗口过大
        "maxWindowWidth": 1920,
        "maxWindowHeight": 1080,
        // 宽高比限制:保持UI布局合理性
        "minWindowRatio": 0.5,   // 最小宽高比 1:2
        "maxWindowRatio": 2.0    // 最大宽高比 2:1
      }
    ]
  }
}

配置建议

应用类型 最小宽度 最小高度 最大宽度 最大高度 说明
文档编辑器 800 600 1920 1080 需要足够的编辑空间
聊天应用 400 500 1200 900 可以保持较小窗口
图片查看器 300 300 无限制 无限制 根据图片尺寸自适应
开发工具 1024 768 无限制 无限制 需要大工作区域
设置面板 500 400 800 600 固定范围,保持紧凑

常见错误对照表

在开发过程中,容易混淆的配置项和API:

错误用法 正确用法 说明
windowResizable: true supportWindowMode: ["floating"] 配置文件中不存在windowResizable属性
windowMode: "floating" supportWindowMode: ["floating"] 应使用数组格式的supportWindowMode
supportWindowMode: ["fixed"] supportWindowMode: ["fullscreen"] 不存在fixed模式,应使用fullscreen
mainWindow.setWindowResizable() 配置文件设置 不存在此API,应通过配置文件控制
mainWindow.setWindowMode() 配置文件设置 不存在此API,应通过配置文件控制
mainWindow.setWindowMinSize() 配置minWindowWidth/Height 不存在此API,应通过配置文件设置
window.WindowMode.FLOATING 配置文件设置 不存在WindowMode枚举

调试技巧

查看当前窗口模式

在代码中可以获取当前窗口的状态信息:

windowStage.getMainWindow((err, mainWindow) => {
  if (err) {
    return;
  }
  
  // 获取窗口属性
  mainWindow.getProperties((err, properties) => {
    if (err) {
      return;
    }
    
    hilog.info(DOMAIN, 'testTag', 'Window width: %{public}d', properties.windowRect.width);
    hilog.info(DOMAIN, 'testTag', 'Window height: %{public}d', properties.windowRect.height);
    hilog.info(DOMAIN, 'testTag', 'Window mode: %{public}d', properties.mode);
  });
});

验证配置是否生效

构建后可以查看生成的 module.json 文件(在 build/intermediates/merge_profile/default/ 目录下),确认配置是否正确合并:

{
  "module": {
    "abilities": [
      {
        "name": "EntryAbility",
        "supportWindowMode": ["fullscreen"]
      }
    ]
  }
}

完整修复流程

步骤一:清理错误配置

首先检查 module.json5 文件,移除所有无效的配置项:

// ❌ 删除这些无效配置
"windowResizable": true,
"windowMode": "floating"

步骤二:添加正确配置

根据需求添加正确的窗口模式配置:

// ✅ 窗口不可缩放
"supportWindowMode": ["fullscreen"]

// 或 ✅ 窗口可缩放
"supportWindowMode": ["fullscreen", "floating"],
"minWindowWidth": 400,
"minWindowHeight": 300

步骤三:清理错误代码

检查 EntryAbility.ets 文件,移除所有不存在的API调用:

// ❌ 删除这些不存在的API
mainWindow.setWindowResizable(true);
mainWindow.setWindowMode(window.WindowMode.FLOATING);
mainWindow.setWindowMinSize(400, 300);
mainWindow.setWindowPreferredSize(800, 600);

步骤四:重新构建

完成修改后,执行构建命令验证:

hvigorw --mode module -p module=entry@default -p product=default assembleHap

总结

鸿蒙PC端窗口配置与传统桌面应用开发有显著差异,主要体现在:

  1. 配置优先:窗口行为通过配置文件声明,而非代码动态设置
  2. 模式明确:三种窗口模式(fullscreen、split、floating)对应不同的用户交互方式
  3. API受限:不存在传统桌面开发中的窗口设置API,需要适应新的开发模式

理解这些差异,正确使用配置文件,是开发鸿蒙PC应用的基础。遇到类似问题时,应该:

  1. 查阅官方文档,确认配置项和API的有效性
  2. 理解配置与代码的职责划分
  3. 使用正确的配置方式实现需求
  4. 通过构建日志定位具体错误位置

希望本文能帮助开发者快速解决鸿蒙PC端窗口配置问题,避免踩坑。

Logo

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

更多推荐