Glass Material Adaptation for ArkTS Widgets (for System Applications Only)
Starting from API version 22, Form Kit supports the glass material effect for system applications, which enhances visual presentation and delivers a premium and refined user experience.
NOTE
- This feature has high requirements for product power consumption and performance, and is currently only supported on certain flagship models.
How to Develop
-
Configure the
entry/src/main/resources/base/profile/form_config.jsonfile.- Add the
visualEffectTypeconfiguration tometadatain the form_config.json file.lightAnimationEffectindicates the glass material. - To achieve the optimal display effect, you are advised to enable widget transparency by adding
"transparencyEnabled": trueto the form_config.json file.
{ "forms": [ { "name": "widget", "displayName": "$string:widget_display_name", "description": "$string:widget_desc", "src": "./ets/widget/pages/WidgetCard.ets", "uiSyntax": "arkts", "window": { "designWidth": 720, "autoDesignWidth": true }, "colorMode": "auto", "isDynamic": true, "isDefault": true, "updateEnabled": false, "scheduledUpdateTime": "10:30", "updateDuration": 1, "defaultDimension": "2*4", "transparencyEnabled": true, "metadata": [ { "name": "visualEffectType", "value": "lightAnimationEffect" } ], "supportDimensions": [ "2*4" ] } ] } - Add the
-
Set the current widget display mode based on the immersive mode switch status.
- The widget provider imports the basic dependency package. Add the following code to
entry/src/main/ets/entryformability/EntryFormAbility.ets:
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit'; import { Want } from '@kit.AbilityKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; const TAG: string = 'EntryFormAbility'; const DOMAIN_NUMBER: number = 0xFF00;- The widget provider transfers the
visualEffectTypeconfiguration in the onAddForm callback.
onAddForm(want: Want) { // Called to return a FormBindingData object. let formData: Record<string, Object> = {}; let wantParams = want.parameters; formData.visualEffectType = String(wantParams?.visualEffectType || 'none'); return formBindingData.createFormBindingData(formData); }- The widget provider updates the
visualEffectTypeconfiguration in the onUpdateForm callback.
onUpdateForm(formId: string, wantParams?: Record<string, Object>) { // Called to notify the form provider to update a specified form. let style: Record<string, Object> = {}; if (wantParams?.visualEffectType) { style.visualEffectType = wantParams?.visualEffectType; let formData: formBindingData.FormBindingData = formBindingData.createFormBindingData(style); formProvider.updateForm(formId, formData).then(() => { hilog.info(DOMAIN_NUMBER, TAG, `onUpdateForm style execute success:${formId}`); }).catch((err: BusinessError) => { hilog.error(DOMAIN_NUMBER, TAG, `onUpdateForm style execute failed:${formId} code: ${(err as BusinessError).code}, message: ${(err as BusinessError).message})`); }); } } - The widget provider imports the basic dependency package. Add the following code to
-
Implement the complete code.
NOTE
- The package must be signed with a system application certificate.
Complete code of
entry/src/main/ets/widget/pages/WidgetCard.ets:import { HdsSceneController, HdsSceneType, HdsVisualComponent, HdsVisualComponentAttribute } from '@kit.UIDesignKit'; let storage: LocalStorage = new LocalStorage(); @Entry (storage) @Component struct WidgetCard { readonly TAG: string = 'WidgetCard'; @LocalStorageProp('formId') formId: string = ''; @LocalStorageProp('visualEffectType') @Watch('dataChange') visualEffectType: string = ''; @State isHarmoniumStyle: boolean = this.visualEffectType === 'lightAnimationEffect'; @State sceneController: HdsSceneController = new HdsSceneController(); @State sigma: number = 5; @State message: string = "Hello World"; @State fontSize: number = 200; @State minFontSize: number = 20; @State maxFontSize: number = 100; @State mirrorFontFamily: string = 'Arial, Noto Sans Regular'; @State fontWeight: FontWeight = FontWeight.Regular; @State color: ResourceColor = Color.White; // Specify the R channel. @State maxLines: number = 1; @State fontFeature: string = '\"ss10\" on'; @State maskProgress: number = 0; @State distortFactor: number = 0; @State rate: number = 0.156; @State lightUpDegree: number = 0.5035; @State cubicCoeff: number = -0.5076; @State quadCoeff: number = 1; @State saturation: number = 1.22; @State posRGB: number[] = [0.47, 1, 0.21]; @State negRGB: number[] = [1, 1, 0.8]; @State fraction: number = 0.75; // Visual effect parameters. @State params: Map<string, Object> = new Map<string, Object>([ ['sigma', this.sigma], ['content', this.message], ['fontSize', this.fontSize], ['maxFontSize', this.maxFontSize], ['minFontSize', this.minFontSize], ['fontFamily', this.mirrorFontFamily], ['fontWeight', this.fontWeight], ['fontColor', this.color], ['fontFeature', this.fontFeature], ['maxLines', this.maxLines], ['maskProgress', this.maskProgress], ['distortFactor', this.distortFactor], ['rate', this.rate], ['lightUpDegree', this.lightUpDegree], ['cubicCoeff', this.cubicCoeff], ['quadCoeff', this.quadCoeff], ['saturation', this.saturation], ['posRGB', this.posRGB], ['negRGB', this.negRGB], ['fraction', this.fraction], ]); aboutToAppear(): void { this.sceneController.setSceneParams(this.params, false); } build() { Column() { if (this.isHarmoniumStyle) { Column() { Row() { HdsVisualComponent() { Text(this.message) .fontColor(this.color) .fontFamily(this.mirrorFontFamily) .fontSize(this.fontSize) .minFontSize(this.minFontSize) .maxFontSize(this.maxFontSize) .fontWeight(this.fontWeight) .fontFeature(this.fontFeature) .maxLines(this.maxLines) .id(`WidgetCard_1`) .fontFeature('\"ss10\" on') .accessibilityLevel('no') .visibility(Visibility.Hidden) } .scene(HdsSceneType.HARMONIUM_MATERIAL_FONT_SCENE, this.sceneController, () => {console.info('callback...');}) } } } else { Stack() { Column() { Text(this.message) .fontColor(this.color) .fontFamily(this.mirrorFontFamily) .fontSize(this.fontSize) .minFontSize(this.minFontSize) .maxFontSize(this.maxFontSize) .fontWeight(this.fontWeight) .fontFeature(this.fontFeature) .maxLines(this.maxLines) .id(`WidgetCard_1`) .fontFeature('\"ss10\" on') .accessibilityLevel('no') } } .height('100%') .width('100%') } } } // Handle property changes. dataChange(propName: string) { switch (propName) { case 'visualEffectType': { console.info(this.TAG, `visualEffectType changed with form=${this.formId},visualEffectType=${this.visualEffectType}`); this.isHarmoniumStyle = this.visualEffectType === 'lightAnimationEffect'; this.sceneController.setSceneParams(this.params, false); break; } default: console.info(this.TAG, `${propName} changed with form=${this.formId}.`); break; } } }