HarmonyOS鸿蒙Next中自定义弹窗修改系统深浅颜色,V2装饰器
HarmonyOS鸿蒙Next中自定义弹窗修改系统深浅颜色,V2装饰器 使用V2装饰器如何实现修改通过自定义弹窗修改系统深浅颜色并且持久化,目前是使用V1才能双向绑定不报错
import { hilog } from '@kit.PerformanceAnalysisKit';
import { ConfigurationConstant } from '@kit.AbilityKit';
@Entry
@ComponentV2
export struct Index {
@Local selectedTheme: string = 'light';
dialogController: CustomDialogController | null = new CustomDialogController({
builder: ThemeSelectDialog({
selectedTheme: $selectedTheme
}),
cancel: () => {
hilog.info(0x0002, '主题弹窗', '点击空白处取消');
},
autoCancel: true,
onWillDismiss:(dismissDialogAction: DismissDialogAction)=> {
console.info(`reason= ${dismissDialogAction.reason}`);
console.info('dialog onWillDismiss')
if (dismissDialogAction.reason == DismissReason.PRESS_BACK) {
dismissDialogAction.dismiss();
}
if (dismissDialogAction.reason == DismissReason.TOUCH_OUTSIDE) {
dismissDialogAction.dismiss();
}
},
alignment: DialogAlignment.Center,
offset: { dx: 0, dy: -20 },
customStyle: false,
cornerRadius: 20,
width: 300,
height: 200,
borderWidth: 1,
borderStyle: BorderStyle.Dashed,// 使用borderStyle属性,需要和borderWidth属性一起使用
borderColor: Color.Blue,// 使用borderColor属性,需要和borderWidth属性一起使用
backgroundColor: Color.White,
shadow: ({ radius: 20, color: Color.Grey, offsetX: 50, offsetY: 0}),
})
aboutToDisappear() {
this.dialogController = null;
}
build() {
Column() {
Column() {
Column() {
HelpCenterComp({
onThemeClick: () => {
if (this.dialogController != null) {
this.dialogController.open();
}
}
})
}
.padding({
left: 16,
right: 16
})
}
.width('100%')
.height('100%')
}
.width('100%')
.height('100%')
.backgroundColor("#f4f4f4")
}
}
@ComponentV2
export struct HelpCenterComp {
@Param breakpoint: string = ''
@Param onThemeClick: () => void = () => {}
@Local callTelSheet: boolean = false
build() {
Column() {
List() {
ListItem() {
Row() {
Row() {
SymbolGlyph($r('sys.symbol.info_circle'))
.fontSize(24)
.fontColor([$r('sys.color.icon_primary'), '#000000'])
}
SymbolGlyph($r('sys.symbol.chevron_right')).fontSize(24).fontColor([$r('sys.color.icon_fourth'), '#000000'])
}
.width('100%')
.padding({ top: 16, bottom: 16 })
.justifyContent(FlexAlign.SpaceBetween)
.onClick(() => {
this.onThemeClick();
})
}
}
.padding({
left: 12,
right: 12,
top: 4,
bottom: 4,
})
.margin({ top: 8 })
.width('100%')
.backgroundColor($r('sys.color.comp_background_list_card'))
.borderRadius(20)
.divider({ strokeWidth: 1, startMargin: 40 })
.edgeEffect(EdgeEffect.Spring, { alwaysEnabled: true })
.enableScrollInteraction(false)
}.margin({ top: 24 }).alignItems(HorizontalAlign.Start)
}
}
@CustomDialog
struct ThemeSelectDialog {
controller?: CustomDialogController;
@Link selectedTheme: string;
build() {
Column({ space: 12 }) {
Text('选择主题模式')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 8 })
.alignSelf(ItemAlign.Center);
List() {
ListItem({ style: ListItemStyle.CARD }) {
Row() {
Column() {
Text('浅色(默认)')
.fontSize(16)
.fontColor(Color.Black);
}
.layoutWeight(1);
Column() {
Radio({ value: 'light', group: 'colorModeRadioGroup' })
.checked(this.selectedTheme === 'light')
.onChange((isChecked: boolean) => {
if (isChecked) {
this.selectedTheme = 'light';
hilog.info(0x0002, '主题切换', '选中浅色模式');
this.switchColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT);
}
});
};
}
.padding({ top: 12, bottom: 12, left: 16, right: 16 });
}
.width('100%')
.backgroundColor(Color.White)
.borderRadius(12);
ListItem({ style: ListItemStyle.CARD }) {
Row() {
Column() {
Text('深色')
.fontSize(16)
.fontColor(Color.Black);
}
.layoutWeight(1);
Column() {
Radio({ value: 'dark', group: 'colorModeRadioGroup' })
.checked(this.selectedTheme === 'dark')
.onChange((isChecked: boolean) => {
if (isChecked) {
this.selectedTheme = 'dark';
this.switchColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK);
}
});
};
}
.padding({ top: 12, bottom: 12, left: 16, right: 16 });
}
.width('100%')
.backgroundColor(Color.White)
.borderRadius(12)
.margin({ top: 8 });
ListItem({ style: ListItemStyle.CARD }) {
Row() {
Column() {
Text('跟随系统')
.fontSize(16)
.fontColor(Color.Black);
}
.layoutWeight(1);
Column() {
Radio({ value: 'system', group: 'colorModeRadioGroup' })
.checked(this.selectedTheme === 'system')
.onChange((isChecked: boolean) => {
if (isChecked) {
this.selectedTheme = 'system';
hilog.info(0x0002, '主题切换', '选中跟随系统');
this.switchColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
}
});
};
}
.padding({ top: 12, bottom: 12, left: 16, right: 16 });
}
.width('100%')
.backgroundColor(Color.White)
.borderRadius(12)
.margin({ top: 8 });
}
.width('100%')
.height(240);
Row({ space: 16 }) {
Button('取消')
.width('40%')
.backgroundColor(Color.Grey)
.fontColor(Color.White)
.onClick(() => {
this.controller?.close();
});
Button('确定')
.width('40%')
.backgroundColor('#0A59F7')
.fontColor(Color.White)
.onClick(() => {
this.controller?.close();
hilog.info(0x0002, '主题切换', '确认选择:%{public}s', this.selectedTheme);
});
}
.margin({ top: 8 })
.width('100%')
.justifyContent(FlexAlign.Center);
}
.width(300)
.padding({ top: 16, bottom: 16 });
}
private switchColorMode(mode: ConfigurationConstant.ColorMode) {
this.getUIContext()
.getHostContext()?.getApplicationContext()
.setColorMode(mode);
}
}
更多关于HarmonyOS鸿蒙Next中自定义弹窗修改系统深浅颜色,V2装饰器的实战教程也可以访问 https://www.itying.com/category-93-b0.html
看这个帖子https://developer.huawei.com/consumer/cn/forum/topic/0210198258639730120?fid=0109140870620153026
更多关于HarmonyOS鸿蒙Next中自定义弹窗修改系统深浅颜色,V2装饰器的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中,使用@CustomDialog装饰器创建自定义弹窗。通过系统API window.getLastWindow(this.context)获取窗口实例,调用setWindowSystemBarEnable方法可控制状态栏和导航栏的显示。系统深浅色模式由系统主题决定,弹窗默认跟随系统主题。弹窗内部UI可通过资源引用系统主题变量(如$color('sys.color.ohos_id_color_foreground'))或条件渲染实现深浅色适配。
在HarmonyOS Next中使用V2装饰器实现自定义弹窗修改系统深浅颜色并持久化,关键在于正确处理状态管理和数据传递。从你的代码看,主要问题在于V2装饰器下状态绑定的方式与V1不同。
核心解决方案:
-
状态管理调整:V2装饰器推荐使用
@State和@Local配合,避免直接使用@Link进行跨组件双向绑定。在弹窗组件中,可以通过回调函数或事件的方式将选择结果传递回父组件。 -
修改弹窗组件:将
ThemeSelectDialog中的@Link selectedTheme: string改为通过参数传递初始值,并通过事件回调传递修改:@CustomDialog struct ThemeSelectDialog { controller?: CustomDialogController; @Param selectedTheme: string; // 改为@Param接收初始值 @Consume themeChangeCallback?: (theme: string) => void; // 回调函数 // 在Radio的onChange中调用回调 .onChange((isChecked: boolean) => { if (isChecked) { const newTheme = 'dark'; // 根据实际情况设置 this.themeChangeCallback?.(newTheme); this.switchColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK); } }) } -
持久化存储:使用
@StorageLink或@StorageProp配合PersistentStorage实现颜色主题的持久化:import { PersistentStorage } from '@kit.ArkData'; // 定义持久化键值 PersistentStorage.persistProp('appTheme', 'light'); @Entry @ComponentV2 export struct Index { @StorageLink('appTheme') selectedTheme: string = 'light'; // 在回调中更新持久化值 handleThemeChange = (theme: string) => { this.selectedTheme = theme; } } -
系统颜色模式设置:你现有的
switchColorMode方法是正确的,通过getUIContext()获取上下文并设置颜色模式。
代码调整要点:
- 将弹窗中的双向绑定改为单向数据流+事件回调
- 使用
@StorageLink实现状态持久化 - 确保弹窗关闭时能正确触发主题更新和持久化保存
这样既符合V2装饰器的状态管理规范,又能实现主题切换的持久化功能。注意在弹窗关闭时,通过回调函数更新父组件的状态并触发持久化存储。

