增加修复了深色模式,完全沉浸的深色模式完成了。

Signed-off-by: laoyang <laoyang@example.com>
This commit is contained in:
laoyang
2026-09-16 21:40:11 +08:00
parent 353473127a
commit d7c49db304
10 changed files with 182 additions and 29 deletions
+106 -25
View File
@@ -1,7 +1,6 @@
import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit';
import { AbilityConstant, ConfigurationConstant, UIAbility, Want, Configuration, EnvironmentCallback } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { BackgroundSyncService } from '../common/BackgroundSyncService';
import { LogUtil } from '../common/LogUtil';
@@ -67,38 +66,120 @@ export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage): void {
hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
// ① 先把应用固定为「跟随系统」深浅色。必须在取窗口/刷系统栏之前调用,
// 否则会读到尚未更新到深色的色彩配置(曾导致深色下状态栏仍是浅灰)。
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));
}
// ② 沉浸式配色:状态栏/导航条背景**透明**,透出「主题化」的窗口底色,
// 消除顶部通知栏与底部灰条;前景(时间/图标)颜色按实际底色亮度取反。
try {
const win: window.Window = windowStage.getMainWindowSync();
this.mainWindow = win;
this.applySystemBars(win);
} catch (err) {
hilog.error(DOMAIN, 'testTag', 'Failed to apply immersive bars. Cause: %{public}s', JSON.stringify(err));
}
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.');
// 沉浸式配色:状态栏/导航条与页面背景同色(app.color.page_bg = #F1F3F5),
// 消除顶部通知栏和底部的白色条
windowStage.getMainWindow((werr: BusinessError, win: window.Window) => {
if (werr.code) {
hilog.error(DOMAIN, 'testTag', 'Failed to get main window. Cause: %{public}s', JSON.stringify(werr));
return;
}
try {
win.setWindowSystemBarProperties({
statusBarColor: '#F1F3F5',
statusBarContentColor: '#182431',
navigationBarColor: '#F1F3F5',
navigationBarContentColor: '#182431'
});
// 鸿蒙 NEXT 导航条背景跟随窗口背景色:设为页面背景灰,消除底部白条
win.setWindowBackgroundColor('#F1F3F5');
} catch (barErr) {
hilog.error(DOMAIN, 'testTag', 'Failed to set system bar properties. Cause: %{public}s',
JSON.stringify(barErr));
}
});
});
// ③ 系统深浅色切换时重刷配色。用 applicationContext 的 environment 回调,
// 它比 UIAbility.onConfigurationUpdate 更可靠(后者在部分场景下不回调,
// 会出现"页面已变深色但状态栏/底部仍是浅灰"的现象)。
try {
this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
const cb: EnvironmentCallback = {
onConfigurationUpdated: (config: Configuration): void => {
if (this.mainWindow !== undefined) {
this.applySystemBars(this.mainWindow);
}
},
onMemoryLevel: (level: AbilityConstant.MemoryLevel): void => {
}
};
this.context.getApplicationContext().on('environment', cb);
} catch (err) {
hilog.error(DOMAIN, 'testTag', 'Failed to set colorMode. Cause: %{public}s', JSON.stringify(err));
hilog.error(DOMAIN, 'testTag', 'Failed to watch environment. Cause: %{public}s', JSON.stringify(err));
}
}
/** 主窗口引用:系统深浅色切换时需要重新刷状态栏/导航栏配色 */
private mainWindow?: window.Window;
/** 当前是否处于系统深色模式(兜底用) */
private isDarkMode(): boolean {
try {
return this.context.config.colorMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK;
} catch (err) {
return false;
}
}
/**
* 取当前主题下 app.color.page_bg 的真实取值(经 dark/ 限定符解析):
* 浅色 #F1F3F5 / 深色 #000000。以"资源系统实际解析出的颜色"为准,
* 这样才能与页面真正渲染出来的背景色一致,不受 config 更新时机影响。
*/
private themePageBg(): string {
try {
const c: number = this.context.resourceManager.getColorSync($r('app.color.page_bg').id) >>> 0;
return '#' + c.toString(16).padStart(8, '0');
} catch (err) {
return this.isDarkMode() ? '#000000' : '#F1F3F5';
}
}
/** 背景是深色时需要浅色前景,反之用深色前景 */
private isDarkBg(bg: string): boolean {
const s: string = bg.startsWith('#') ? bg.substring(1) : bg;
if (s.length < 6) {
return this.isDarkMode();
}
const off: number = s.length >= 8 ? 2 : 0;
const r: number = parseInt(s.substring(off, off + 2), 16);
const g: number = parseInt(s.substring(off + 2, off + 4), 16);
const b: number = parseInt(s.substring(off + 4, off + 6), 16);
if (isNaN(r) || isNaN(g) || isNaN(b)) {
return this.isDarkMode();
}
return (0.2126 * r + 0.7152 * g + 0.0722 * b) < 128;
}
/**
* 按当前主题设置状态栏/导航条与窗口底色。
* 背景取 0x00000000(全透明)——官方推荐的背景沉浸方案:系统栏透明,
* 透传应用自身背景,因此底色天然跟随深浅色,不会再出现恒定灰条。
*/
private applySystemBars(win: window.Window): void {
const bgColor: string = this.themePageBg();
const fgColor: string = this.isDarkBg(bgColor) ? '#FFFFFF' : '#182431';
try {
win.setWindowSystemBarProperties({
statusBarColor: '#00000000',
statusBarContentColor: fgColor,
navigationBarColor: '#00000000',
navigationBarContentColor: fgColor
});
// 窗口底色=页面背景色,供透明的状态栏/导航条透出
win.setWindowBackgroundColor(bgColor);
} catch (barErr) {
hilog.error(DOMAIN, 'testTag', 'Failed to set system bar properties. Cause: %{public}s',
JSON.stringify(barErr));
}
}
/** 兜底:部分设备/场景只回调 UIAbility.onConfigurationUpdate */
onConfigurationUpdate(): void {
if (this.mainWindow !== undefined) {
this.applySystemBars(this.mainWindow);
}
}