Read the original article:How to update widget content from another widget?
Requirement Description
When users add multiple widgets from the same app, the content should be synchronized.
Background Knowledge
- On the widget page, you can trigger a message event via the postCardAction API to launch the FormExtensionAbility. The FormExtensionAbility then notifies the application through the onFormEvent callback. This process enables the functionality of passing messages to the application after a widget is touched.
- The widget provider can call updateForm to actively update the widget.
Implementation Steps
Step 1: Create an application.
Step 2: Define data models.
Step 3: Implement preferences to store data.
Step 4: Create a widget with multiple support dimensions
Step 5: Add widgets and see instant synchronization.
Code Snippet
Step 1: Create an application.
Step 2: Define data models.
- Mode.ets (Basic enumeration data)
// model/Mode.ets
export enum Mode {
sad,
happy
}
- ModelData.ets (To transfer data between widgets)
// model/ModeData.ets
import { Mode } from "./Mode";
export interface ModeData {
mode: Mode,
method: string
}
Step 3: Implement preferences to store data.
- WidgetIdPrefs.ets (To store widget ids)
// util/WidgetIdPrefs.ets
import { Context } from '@kit.AbilityKit';
import { preferences } from '@kit.ArkData';
export default class WidgetIdPrefs {
static addFormID(context: Context, formID: string) {
console.log('addFormID', formID);
let prefs = preferences.getPreferencesSync(context, { name: 'ids' });
prefs.putSync(formID, formID)
prefs.flushSync()
}
static removeFormID(context: Context, formID: string) {
console.log('removeFormID', formID);
let prefs = preferences.getPreferencesSync(context, { name: 'ids' });
prefs.deleteSync(formID)
prefs.flushSync()
}
static getFormIDs(context: Context): string[] {
console.log('getFormIDs');
let prefs = preferences.getPreferencesSync(context, { name: 'ids' });
return Object.values(prefs.getAllSync())
}
}
Step 4: Create a widget with multiple support dimensions. Here we will use "1*2" and "2*2" and name it Widget1. For details about how to create a widget, please visit: Creating an ArkTS Widget
- Widget1Card.ets
// widget1/pages/Widget1Card.ets
import { Mode } from '../../model/Mode'
let ls = new LocalStorage();
@Entry(ls)
@Component
struct MyModeCard {
@LocalStorageProp('mode') mode: Mode = Mode.happy
build() {
Row({ space: 8 }) {
Button('😭')
.fontSize(18)
.backgroundColor(this.mode === Mode.sad ? Color.Red : Color.Grey)
.type(ButtonType.Circle)
.layoutWeight(1)
.onClick(() => {
this.changeMode(Mode.sad)
})
Button('😊')
.fontSize(18)
.backgroundColor(this.mode === Mode.happy ? Color.Green : Color.Grey)
.type(ButtonType.Circle)
.layoutWeight(1)
.onClick(() => {
this.changeMode(Mode.happy)
})
}
.padding(8)
.height('100%')
.backgroundColor($r('sys.color.comp_background_primary'))
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
});
})
}
changeMode(newMode: Mode) {
if (this.mode !== newMode) {
this.postCardActionCall(newMode)
}
}
postCardActionCall(newMode: Mode) {
postCardAction(this, {
action: 'message',
abilityName: 'EntryAbility',
params: {
// function name
method: 'changeMode',
// additional parameters
mode: newMode
}
});
}
}
- Modify Widget1FormAbility.ets to add and remove widget IDs and to capture message action.
// widget1formability/Widget1FormAbility.ets
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
import WidgetIdPrefs from '../util/WidgetIdPrefs';
import { ModeData } from '../model/ModeData';
import { vibrator } from '@kit.SensorServiceKit';
export default class Widget1FormAbility extends FormExtensionAbility {
onAddForm(want: Want) {
// Called to return a FormBindingData object.
if (!want || !want.parameters) {
console.error(`FormAbility onAddForm want or want.parameters is undefined`);
return formBindingData.createFormBindingData('');
}
// store form id
let formId: string = want.parameters[formInfo.FormParam.IDENTITY_KEY] as string;
WidgetIdPrefs.addFormID(this.context, formId);
const formData = '';
return formBindingData.createFormBindingData(formData);
}
onCastToNormalForm(formId: string) {
// Called when the form provider is notified that a temporary form is successfully
// converted to a normal form.
}
onUpdateForm(formId: string) {
// Called to notify the form provider to update a specified form.
}
onFormEvent(formId: string, message: string) {
// Called when a specified message event defined by the form provider is triggered.
let data: ModeData = JSON.parse(message);
// update widget content
if (data.method === 'changeMode') {
vibrator.startVibration({ type: 'time', duration: 200 }, { usage: 'physicalFeedback' })
const ids = WidgetIdPrefs.getFormIDs(this.context)
ids.forEach((id: string) => {
let formInfo: formBindingData.FormBindingData = formBindingData.createFormBindingData(data);
formProvider.updateForm(id, formInfo)
})
}
}
onRemoveForm(formId: string) {
// Called to notify the form provider that a specified form has been destroyed.
// remove form id
WidgetIdPrefs.removeFormID(this.context, formId);
}
onAcquireFormState(want: Want) {
// Called to return a {@link FormState} object.
return formInfo.FormState.READY;
}
}
Step 5: Add widgets and see instant synchronization.
Top comments (0)