HarmonyOS开发中的显示设置全解析

举报
Jack20 发表于 2026/06/20 19:22:26 2026/06/20
【摘要】 HarmonyOS APP开发中的显示设置全解析:从亮度调节到折叠屏适配,掌控每一块屏幕📌 核心要点:HarmonyOS 提供完整的显示设置 API,涵盖亮度、方向、超时、分辨率和折叠屏适配,让应用在不同设备上都有最佳视觉体验 一、背景与动机你有没有这样的体验——晚上躺在床上刷手机,屏幕亮得像探照灯,刺得眼睛生疼;或者看电子书时,屏幕突然自己转了方向,文字全歪了;又或者手机放在桌上忘了锁...

HarmonyOS APP开发中的显示设置全解析:从亮度调节到折叠屏适配,掌控每一块屏幕

📌 核心要点:HarmonyOS 提供完整的显示设置 API,涵盖亮度、方向、超时、分辨率和折叠屏适配,让应用在不同设备上都有最佳视觉体验


一、背景与动机

你有没有这样的体验——晚上躺在床上刷手机,屏幕亮得像探照灯,刺得眼睛生疼;或者看电子书时,屏幕突然自己转了方向,文字全歪了;又或者手机放在桌上忘了锁屏,回来一看电量掉了一半……

这些都是显示设置要解决的问题。作为开发者,我们不仅要让应用"能用",还要让它在各种显示环境下都"好用"——该亮的时候亮,该暗的时候暗,该横的时候横,该竖的时候竖。

HarmonyOS 的 @ohos.display 模块提供了全面的显示控制能力。从最基础的亮度调节,到复杂的折叠屏适配,它都能搞定。

典型使用场景:

  • 阅读器:根据环境光自动调节亮度,阅读时锁定竖屏
  • 视频播放器:播放时切换横屏、保持常亮
  • 导航应用:全程保持屏幕常亮,避免息屏
  • 折叠屏应用:展开时显示平板布局,折叠时显示手机布局

二、核心原理

2.1 显示设置体系架构

图片.png

flowchart TB
    A[应用层] --> B[显示设置管理]
    B --> C[屏幕亮度]
    B --> D[屏幕方向]
    B --> E[屏幕超时]
    B --> F[分辨率/刷新率]
    B --> G[折叠屏适配]
    
    C --> C1[系统亮度值]
    C --> C2[自动亮度]
    C --> C3[窗口亮度覆盖]
    
    D --> D1[竖屏/横屏]
    D --> D2[方向锁定]
    D --> D3[传感器跟随]
    
    E --> E1[休眠超时]
    E --> E2[保持常亮]
    
    F --> F1[分辨率切换]
    F --> F2[高刷新率]
    
    G --> G1[折叠状态监听]
    G --> G2[布局自适应]
    G --> G3[窗口尺寸变化]
    
    classDef primary fill:#4CAF50,stroke:#388E3C,color:#fff
    classDef warning fill:#FF9800,stroke:#F57C00,color:#fff
    classDef error fill:#F44336,stroke:#D32F2F,color:#fff
    classDef info fill:#2196F3,stroke:#1976D2,color:#fff
    classDef purple fill:#9C27B0,stroke:#7B1FA2,color:#fff
    
    class A primary
    class B info
    class C,D,E,F,G warning
    class C1,C2,C3,D1,D2,D3,E1,E2,F1,F2,G1,G2,G3 purple

2.2 核心模块与 API

模块 核心 API 说明
@ohos.display getDefaultDisplaySync() 获取默认屏幕信息
@ohos.display on('foldStatusChange') 监听折叠状态变化
@ohos.display on('displaySizeChange') 监听屏幕尺寸变化
@ohos.window setWindowBrightness() 设置窗口亮度
@ohos.window setPreferredOrientation() 设置屏幕方向
@ohos.window setWindowKeepScreenOn() 设置保持常亮

2.3 亮度控制层级

flowchart LR
    A[系统全局亮度] -->|0~255| B[亮度值]
    C[自动亮度开关] -->|/| B
    D[窗口亮度覆盖] -->|0~1.0| E[当前窗口亮度]
    B -->|基础值| E
    
    classDef primary fill:#4CAF50,stroke:#388E3C,color:#fff
    classDef warning fill:#FF9800,stroke:#F57C00,color:#fff
    classDef error fill:#F44336,stroke:#D32F2F,color:#fff
    classDef info fill:#2196F3,stroke:#1976D2,color:#fff
    classDef purple fill:#9C27B0,stroke:#7B1FA2,color:#fff
    
    class A primary
    class C warning
    class D info
    class E primary

关键理解:窗口亮度是覆盖系统亮度的。就像你在灯光通明的房间里又开了一盏台灯——台灯的亮度只影响你桌面的区域,不影响整个房间。同理,窗口亮度只影响当前应用窗口,退出应用后恢复系统亮度。


三、代码实战

3.1 屏幕亮度调节:阅读器的护眼模式

阅读器对亮度的要求很特殊——不能太亮刺眼,也不能太暗看不清。最佳方案是跟随系统自动亮度,同时允许用户微调。

import { window } from '@kit.ArkUI';
import { display } from '@kit.ArkUI';

/**
 * 亮度管理器
 * 封装屏幕亮度相关操作
 */
class BrightnessManager {
  private mainWindow: window.Window | null = null;

  /**
   * 初始化,获取主窗口
   */
  async init(context: Context): Promise<void> {
    const windowStage = window.findWindow('MainWindow');
    if (windowStage) {
      this.mainWindow = windowStage;
    } else {
      // 通过 context 获取窗口
      this.mainWindow = await window.getLastWindow(context);
    }
  }

  /**
   * 设置窗口亮度(0.0 ~ 1.0)
   * 只影响当前窗口,不影响系统亮度
   * @param brightness 亮度值,0.0 最暗,1.0 最亮
   */
  async setWindowBrightness(brightness: number): Promise<void> {
    if (!this.mainWindow) {
      console.error('[Brightness] 窗口未初始化');
      return;
    }

    // 限制范围
    const clamped = Math.max(0, Math.min(1, brightness));

    try {
      await this.mainWindow.setWindowBrightness(clamped);
      console.info(`[Brightness] 窗口亮度设置: ${clamped}`);
    } catch (err) {
      console.error(`[Brightness] 设置失败: ${JSON.stringify(err)}`);
    }
  }

  /**
   * 获取当前窗口亮度
   */
  async getWindowBrightness(): Promise<number> {
    if (!this.mainWindow) return -1;
    try {
      const properties = await this.mainWindow.getWindowProperties();
      return properties.brightness;
    } catch (err) {
      console.error(`[Brightness] 获取失败: ${JSON.stringify(err)}`);
      return -1;
    }
  }

  /**
   * 重置窗口亮度为系统默认
   * 传入 -1 表示跟随系统
   */
  async resetWindowBrightness(): Promise<void> {
    if (!this.mainWindow) return;
    try {
      await this.mainWindow.setWindowBrightness(-1);
      console.info('[Brightness] 已重置为系统亮度');
    } catch (err) {
      console.error(`[Brightness] 重置失败: ${JSON.stringify(err)}`);
    }
  }

  /**
   * 获取系统屏幕亮度(0 ~ 255)
   */
  getSystemBrightness(): number {
    try {
      const displayInfo = display.getDefaultDisplaySync();
      // 通过 display 获取亮度需要系统 API 权限
      // 普通应用建议使用窗口亮度覆盖
      return 128; // 默认值
    } catch (err) {
      return 128;
    }
  }
}

/**
 * 阅读器亮度控制页面
 */
@Entry
@Component
struct ReaderBrightnessPage {
  @State currentBrightness: number = 0.5;
  @State isFollowSystem: boolean = true;
  private brightnessManager: BrightnessManager = new BrightnessManager();

  async aboutToAppear(): Promise<void> {
    const context = getContext(this);
    await this.brightnessManager.init(context);

    // 读取当前窗口亮度
    const brightness = await this.brightnessManager.getWindowBrightness();
    if (brightness >= 0) {
      this.currentBrightness = brightness;
      this.isFollowSystem = brightness < 0; // -1 表示跟随系统
    }
  }

  build() {
    Column() {
      // 标题
      Text('阅读亮度设置')
        .fontSize(22)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 24 })

      // 亮度预览区域
      Column() {
        Text('这是一段示例文字,用于预览当前亮度效果。')
          .fontSize(16)
          .lineHeight(28)
          .padding(20)
      }
      .width('100%')
      .height(200)
      .backgroundColor('#FFF8E1')
      .borderRadius(16)
      .justifyContent(FlexAlign.Center)
      .margin({ bottom: 24 })

      // 跟随系统开关
      Row() {
        Text('跟随系统亮度')
          .fontSize(16)
          .layoutWeight(1)
        Toggle({ type: ToggleType.Switch, isOn: this.isFollowSystem })
          .onChange(async (isOn: boolean) => {
            this.isFollowSystem = isOn;
            if (isOn) {
              await this.brightnessManager.resetWindowBrightness();
            } else {
              await this.brightnessManager.setWindowBrightness(this.currentBrightness);
            }
          })
      }
      .width('100%')
      .padding({ left: 16, right: 16 })
      .margin({ bottom: 20 })

      // 亮度滑块
      Column() {
        Row() {
          Text('☀️')
            .fontSize(14)
          Slider({
            value: this.currentBrightness * 100,
            min: 0,
            max: 100,
            step: 5,
            style: SliderStyle.OutSet
          })
            .layoutWeight(1)
            .onChange(async (value: number) => {
              this.currentBrightness = value / 100;
              if (!this.isFollowSystem) {
                await this.brightnessManager.setWindowBrightness(this.currentBrightness);
              }
            })
          Text('🔆')
            .fontSize(20)
        }
        .width('100%')

        Text(`亮度: ${Math.round(this.currentBrightness * 100)}%`)
          .fontSize(14)
          .fontColor('#666')
          .margin({ top: 8 })
      }
      .width('100%')
      .padding(16)
      .backgroundColor('#f5f5f5')
      .borderRadius(12)

      // 快捷亮度预设
      Row() {
        this.QuickButton('夜间', 0.15)
        this.QuickButton('柔和', 0.35)
        this.QuickButton('标准', 0.55)
        this.QuickButton('明亮', 0.8)
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceAround)
      .margin({ top: 20 })
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }

  @Builder
  QuickButton(label: string, brightness: number) {
    Button(label)
      .fontSize(14)
      .backgroundColor(this.currentBrightness === brightness ? '#4CAF50' : '#e0e0e0')
      .fontColor(this.currentBrightness === brightness ? '#fff' : '#333')
      .borderRadius(20)
      .width(70)
      .height(36)
      .onClick(async () => {
        this.currentBrightness = brightness;
        this.isFollowSystem = false;
        await this.brightnessManager.setWindowBrightness(brightness);
      })
  }
}

export { BrightnessManager };

3.2 屏幕方向锁定与超时设置:视频播放器场景

视频播放器有两个刚需:播放时横屏、播放时常亮。这两个需求通过 setPreferredOrientationsetWindowKeepScreenOn 实现。

import { window } from '@kit.ArkUI';

/**
 * 屏幕方向与超时管理器
 */
class DisplayControlManager {
  private mainWindow: window.Window | null = null;

  /**
   * 初始化
   */
  async init(context: Context): Promise<void> {
    this.mainWindow = await window.getLastWindow(context);
  }

  /**
   * 设置屏幕方向
   * @param orientation 方向枚举
   */
  async setOrientation(orientation: window.Orientation): Promise<void> {
    if (!this.mainWindow) return;
    try {
      await this.mainWindow.setPreferredOrientation(orientation);
      const nameMap: Record<number, string> = {
        0: '未指定',
        1: '竖屏',
        2: '横屏(左旋)',
        3: '横屏(右旋)',
        4: '反向竖屏',
        5: '传感器自动旋转',
        6: '传感器竖屏',
        7: '传感器横屏',
      };
      console.info(`[Display] 屏幕方向: ${nameMap[orientation] || orientation}`);
    } catch (err) {
      console.error(`[Display] 设置方向失败: ${JSON.stringify(err)}`);
    }
  }

  /**
   * 锁定竖屏
   */
  async lockPortrait(): Promise<void> {
    await this.setOrientation(window.Orientation.PORTRAIT);
  }

  /**
   * 锁定横屏
   */
  async lockLandscape(): Promise<void> {
    await this.setOrientation(window.Orientation.LANDSCAPE);
  }

  /**
   * 自动旋转(跟随传感器)
   */
  async autoRotate(): Promise<void> {
    await this.setOrientation(window.Orientation.AUTO_ROTATION);
  }

  /**
   * 设置屏幕保持常亮
   * @param keepOn true=常亮,false=跟随系统超时
   */
  async setKeepScreenOn(keepOn: boolean): Promise<void> {
    if (!this.mainWindow) return;
    try {
      await this.mainWindow.setWindowKeepScreenOn(keepOn);
      console.info(`[Display] 屏幕常亮: ${keepOn ? '开启' : '关闭'}`);
    } catch (err) {
      console.error(`[Display] 设置常亮失败: ${JSON.stringify(err)}`);
    }
  }

  /**
   * 获取当前屏幕方向
   */
  async getCurrentOrientation(): Promise<window.Orientation> {
    if (!this.mainWindow) return window.Orientation.UNSPECIFIED;
    try {
      const properties = await this.mainWindow.getWindowProperties();
      return properties.orientation;
    } catch (err) {
      return window.Orientation.UNSPECIFIED;
    }
  }
}

/**
 * 视频播放器页面
 * 播放时自动横屏 + 常亮
 */
@Entry
@Component
struct VideoPlayerPage {
  @State isPlaying: boolean = false;
  @State isFullscreen: boolean = false;
  private displayControl: DisplayControlManager = new DisplayControlManager();

  async aboutToAppear(): Promise<void> {
    const context = getContext(this);
    await this.displayControl.init(context);
  }

  /**
   * 进入全屏播放
   */
  async enterFullscreen(): Promise<void> {
    this.isFullscreen = true;
    // 横屏 + 常亮
    await this.displayControl.lockLandscape();
    await this.displayControl.setKeepScreenOn(true);

    // 隐藏状态栏(沉浸式)
    const mainWindow = await window.getLastWindow(getContext(this));
    await mainWindow.setWindowLayoutFullScreen(true);
  }

  /**
   * 退出全屏播放
   */
  async exitFullscreen(): Promise<void> {
    this.isFullscreen = false;
    // 恢复竖屏 + 取消常亮
    await this.displayControl.lockPortrait();
    await this.displayControl.setKeepScreenOn(false);

    // 恢复状态栏
    const mainWindow = await window.getLastWindow(getContext(this));
    await mainWindow.setWindowLayoutFullScreen(false);
  }

  build() {
    Column() {
      // 视频区域
      Stack() {
        // 视频占位
        Column() {
          Text('🎬')
            .fontSize(48)
          Text(this.isPlaying ? '播放中...' : '已暂停')
            .fontSize(14)
            .fontColor('#fff')
            .margin({ top: 8 })
        }
        .width('100%')
        .height(this.isFullscreen ? '100%' : 220)
        .backgroundColor('#000')
        .justifyContent(FlexAlign.Center)
        .onClick(async () => {
          this.isPlaying = !this.isPlaying;
          if (this.isPlaying) {
            await this.displayControl.setKeepScreenOn(true);
          }
        })

        // 全屏按钮
        if (!this.isFullscreen) {
          Button(this.isFullscreen ? '退出全屏' : '全屏')
            .fontSize(12)
            .backgroundColor('#80000000')
            .position({ x: '80%', y: 10 })
            .onClick(() => this.enterFullscreen())
        }

        // 退出全屏按钮
        if (this.isFullscreen) {
          Button('退出')
            .fontSize(12)
            .backgroundColor('#80000000')
            .position({ x: 10, y: 10 })
            .onClick(() => this.exitFullscreen())
        }
      }
      .width('100%')
      .height(this.isFullscreen ? '100%' : 220)

      // 非全屏时显示控制面板
      if (!this.isFullscreen) {
        Column() {
          Text('播放控制')
            .fontSize(18)
            .fontWeight(FontWeight.Bold)
            .margin({ bottom: 16 })

          Row() {
            Button('播放/暂停')
              .onClick(() => {
                this.isPlaying = !this.isPlaying;
              })
            Button('全屏播放')
              .onClick(() => this.enterFullscreen())
          }
          .width('100%')
          .justifyContent(FlexAlign.SpaceAround)
        }
        .width('100%')
        .padding(20)
      }
    }
    .width('100%')
    .height('100%')
  }

  /**
   * 页面销毁时恢复设置
   */
  async aboutToDisappear(): Promise<void> {
    if (this.isFullscreen) {
      await this.exitFullscreen();
    }
  }
}

export { DisplayControlManager };

3.3 折叠屏适配:展开/折叠的布局响应

折叠屏是 HarmonyOS 生态的明星特性。应用需要根据折叠状态切换布局——折叠时是手机布局,展开时是平板布局。

import { display } from '@kit.ArkUI';

/**
 * 折叠屏适配管理器
 * 监听折叠状态变化,提供布局建议
 */
class FoldableManager {
  private foldStatus: display.FoldStatus = display.FoldStatus.FOLD_STATUS_UNKNOWN;
  private listeners: ((status: display.FoldStatus) => void)[] = [];

  /**
   * 折叠状态枚举说明:
   * FOLD_STATUS_UNKNOWN = 0    未知
   * FOLD_STATUS_EXPANDED = 1   展开(平板模式)
   * FOLD_STATUS_FOLDED = 2     折叠(手机模式)
   * FOLD_STATUS_HALF_FOLDED = 3 半折叠(帐篷/笔记本模式)
   */

  /**
   * 初始化折叠屏监听
   */
  init(): void {
    // 获取当前折叠状态
    try {
      this.foldStatus = display.getFoldStatusSync();
      console.info(`[Foldable] 初始状态: ${this.foldStatus}`);
    } catch (err) {
      console.warn(`[Foldable] 获取折叠状态失败: ${JSON.stringify(err)}`);
    }

    // 监听折叠状态变化
    display.on('foldStatusChange', (status: display.FoldStatus) => {
      console.info(`[Foldable] 折叠状态变更: ${this.foldStatus}${status}`);
      this.foldStatus = status;
      this.notifyListeners(status);
    });
  }

  /**
   * 是否展开状态
   */
  isExpanded(): boolean {
    return this.foldStatus === display.FoldStatus.FOLD_STATUS_EXPANDED;
  }

  /**
   * 是否折叠状态
   */
  isFolded(): boolean {
    return this.foldStatus === display.FoldStatus.FOLD_STATUS_FOLDED;
  }

  /**
   * 是否半折叠状态
   */
  isHalfFolded(): boolean {
    return this.foldStatus === display.FoldStatus.FOLD_STATUS_HALF_FOLDED;
  }

  /**
   * 获取当前布局模式建议
   */
  getLayoutMode(): 'phone' | 'tablet' | 'tent' {
    switch (this.foldStatus) {
      case display.FoldStatus.FOLD_STATUS_EXPANDED:
        return 'tablet';
      case display.FoldStatus.FOLD_STATUS_HALF_FOLDED:
        return 'tent';
      case display.FoldStatus.FOLD_STATUS_FOLDED:
      default:
        return 'phone';
    }
  }

  /**
   * 注册状态变更监听
   */
  onFoldStatusChange(callback: (status: display.FoldStatus) => void): void {
    this.listeners.push(callback);
  }

  /**
   * 通知监听器
   */
  private notifyListeners(status: display.FoldStatus): void {
    this.listeners.forEach(cb => cb(status));
  }

  /**
   * 销毁监听
   */
  destroy(): void {
    display.off('foldStatusChange');
    this.listeners = [];
  }
}

/**
 * 折叠屏自适应页面
 * 根据折叠状态切换手机/平板布局
 */
@Entry
@Component
struct FoldableAdaptivePage {
  @State layoutMode: 'phone' | 'tablet' | 'tent' = 'phone';
  @State screenWidth: number = 360;
  @State screenHeight: number = 800;
  private foldableManager: FoldableManager = new FoldableManager();

  aboutToAppear(): void {
    this.foldableManager.init();
    this.layoutMode = this.foldableManager.getLayoutMode();

    // 监听折叠状态变化
    this.foldableManager.onFoldStatusChange((status) => {
      this.layoutMode = this.foldableManager.getLayoutMode();
    });

    // 监听屏幕尺寸变化
    display.on('displaySizeChange', display.getDefaultDisplaySync().id, (data) => {
      this.screenWidth = px2vp(data.width);
      this.screenHeight = px2vp(data.height);
      console.info(`[Foldable] 屏幕尺寸: ${this.screenWidth}x${this.screenHeight}`);
    });

    // 获取初始屏幕尺寸
    const displayInfo = display.getDefaultDisplaySync();
    this.screenWidth = px2vp(displayInfo.width);
    this.screenHeight = px2vp(displayInfo.height);
  }

  aboutToDisappear(): void {
    this.foldableManager.destroy();
    display.off('displaySizeChange');
  }

  build() {
    if (this.layoutMode === 'tablet') {
      // 平板布局:双栏
      this.TabletLayout()
    } else if (this.layoutMode === 'tent') {
      // 帐篷模式:上下分区
      this.TentLayout()
    } else {
      // 手机布局:单栏
      this.PhoneLayout()
    }
  }

  /**
   * 手机布局:单栏列表
   */
  @Builder
  PhoneLayout() {
    Column() {
      Text('📱 手机模式')
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 16 })

      // 列表内容
      List() {
        ForEach(['推荐内容', '热门话题', '最新发布', '关注动态', '附近的人'], (item: string) => {
          ListItem() {
            Row() {
              Text('📄')
                .fontSize(24)
                .margin({ right: 12 })
              Text(item)
                .fontSize(16)
                .layoutWeight(1)
            }
            .width('100%')
            .padding(16)
            .backgroundColor('#f5f5f5')
            .borderRadius(12)
            .margin({ bottom: 8 })
          }
        })
      }
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .padding(16)
  }

  /**
   * 平板布局:双栏
   */
  @Builder
  TabletLayout() {
    Row() {
      // 左侧:导航列表
      Column() {
        Text('📋 导航')
          .fontSize(18)
          .fontWeight(FontWeight.Bold)
          .margin({ bottom: 16 })

        ForEach(['推荐内容', '热门话题', '最新发布', '关注动态', '附近的人'], (item: string) => {
          Text(item)
            .fontSize(16)
            .padding(12)
            .borderRadius(8)
            .width('100%')
            .margin({ bottom: 4 })
            .backgroundColor('#f0f0f0')
        })
      }
      .width('35%')
      .height('100%')
      .padding(16)
      .backgroundColor('#fafafa')

      // 右侧:内容详情
      Column() {
        Text('📖 内容详情')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
          .margin({ bottom: 16 })

        Column() {
          Text('展开模式下的详细内容区域')
            .fontSize(16)
            .lineHeight(28)
          Text('可以展示更丰富的信息,充分利用大屏空间')
            .fontSize(14)
            .fontColor('#666')
            .margin({ top: 12 })
        }
        .padding(20)
        .backgroundColor('#fff')
        .borderRadius(12)
        .layoutWeight(1)
      }
      .layoutWeight(1)
      .height('100%')
      .padding(16)
    }
    .width('100%')
    .height('100%')
  }

  /**
   * 帐篷模式:上下分区
   */
  @Builder
  TentLayout() {
    Column() {
      // 上半屏:展示区
      Column() {
        Text('🏕️ 帐篷模式 - 展示区')
          .fontSize(18)
          .fontWeight(FontWeight.Bold)
        Text('适合放在桌面上查看')
          .fontSize(14)
          .fontColor('#666')
          .margin({ top: 8 })
      }
      .width('100%')
      .layoutWeight(1)
      .justifyContent(FlexAlign.Center)
      .backgroundColor('#E3F2FD')

      // 下半屏:控制区
      Column() {
        Text('控制面板')
          .fontSize(16)
          .fontWeight(FontWeight.Bold)
          .margin({ bottom: 12 })

        Row() {
          Button('◀ 上一项')
          Button('▶ 下一项')
        }
        .width('100%')
        .justifyContent(FlexAlign.SpaceAround)
      }
      .width('100%')
      .height(180)
      .padding(16)
      .backgroundColor('#fafafa')
    }
    .width('100%')
    .height('100%')
  }
}

export { FoldableManager };

四、踩坑与注意事项

4.1 窗口亮度 vs 系统亮度

:应用内修改亮度后,退出应用发现系统亮度也被改了。

:使用 setWindowBrightness() 只影响当前窗口,退出后自动恢复。千万不要用系统 API 修改全局亮度——那需要系统级权限,而且会影响用户的其他应用。

4.2 setPreferredOrientation 的时机

:在 aboutToAppear 中设置方向,但页面已经渲染了竖屏布局,切换后布局错乱。

:在 onWindowStageCreate 阶段就设置方向,或者在设置方向后延迟 100ms 再加载内容。

// ✅ 正确:提前设置方向
onWindowStageCreate() {
  window.getLastWindow(context).then(win => {
    win.setPreferredOrientation(window.Orientation.LANDSCAPE);
  });
}

4.3 setWindowKeepScreenOn 的电量消耗

:忘记关闭常亮,导致电量快速消耗。

:在页面 aboutToDisappear 中务必关闭常亮。对于视频播放器,暂停时也应考虑关闭。

4.4 折叠屏的 displaySizeChange 频繁触发

:折叠/展开过程中,displaySizeChange 会连续触发多次,导致布局频繁重绘。

:加入防抖,只在尺寸稳定后执行布局切换。

private resizeTimer: number = -1;

display.on('displaySizeChange', displayId, (data) => {
  if (this.resizeTimer !== -1) {
    clearTimeout(this.resizeTimer);
  }
  this.resizeTimer = setTimeout(() => {
    this.handleResize(data.width, data.height);
  }, 300);
});

4.5 半折叠模式的特殊处理

:半折叠(帐篷模式)时,屏幕被物理分为上下两半,但系统仍然认为是一个完整屏幕。

:在半折叠模式下,主动将布局分为上下两个区域,上半部分展示内容,下半部分提供控制。


五、HarmonyOS 6 适配

5.1 API 变化一览

变化项 HarmonyOS 5 HarmonyOS 6
折叠状态 3 种(展开/折叠/半折叠) 新增 FOLD_STATUS_FULL_EXPANDED(完全展开)
刷新率 无法主动设置 新增 setDisplayRefreshRate()
HDR 不支持 新增 HDR 显示模式支持
多屏协同 基础支持 新增跨屏拖拽、无缝切换
屏幕圆角 不感知 新增 display.getCutoutInfo() 获取刘海/挖孔信息

5.2 迁移指南

// HarmonyOS 5:无法设置刷新率
// 只能读取 display.getDefaultDisplaySync().refreshRate

// HarmonyOS 6:可以主动设置刷新率
import { display } from '@kit.ArkUI';
display.setDisplayRefreshRate(displayId, 120); // 设置 120Hz

5.3 注意事项

  1. 刷新率设置:高刷新率会增加功耗,建议仅在游戏等场景开启,普通场景使用 60Hz。
  2. HDR 模式:需要屏幕硬件支持,使用前应检查 isHdrSupported()
  3. 刘海/挖孔适配:HarmonyOS 6 新增的 getCutoutInfo() 可以获取屏幕异形区域,避免内容被遮挡。

六、总结

mindmap
  root((显示设置))
    屏幕亮度
      窗口亮度覆盖
      跟随系统亮度
      阅读器护眼模式
    屏幕方向
      竖屏/横屏锁定
      传感器自动旋转
      视频播放器场景
    屏幕超时
      保持常亮
      播放/导航场景
      记得关闭常亮
    分辨率与刷新率
      高刷新率设置(HarmoneyOS 6HDR 模式
      功耗与体验平衡
    折叠屏适配
      折叠状态监听
      手机/平板布局切换
      半折叠帐篷模式
      防抖处理
    注意事项
      窗口亮度 vs 系统亮度
      方向设置时机
      常亮电量消耗
      尺寸变化防抖
知识点 要点
亮度控制 使用窗口亮度覆盖,不修改系统全局亮度
方向控制 setPreferredOrientation 设置方向,视频场景横屏+常亮
保持常亮 setWindowKeepScreenOn(true),退出时务必关闭
折叠屏 监听 foldStatusChange,根据状态切换布局模式
防抖 折叠/尺寸变化时加入防抖,避免频繁重绘
HarmonyOS 6 新增刷新率设置、HDR 模式、刘海/挖孔信息

显示设置就像给应用穿衣服——不同场合穿不同的衣服。阅读时穿"护眼模式",看视频时穿"横屏常亮",折叠屏展开时换上"平板正装"。掌握了这些,你的应用就能在任何屏幕上都体面登场。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。