diff --git a/README_EN.md b/README.en.md similarity index 88% rename from README_EN.md rename to README.en.md index a0f34f9b0c411b1385d8c50d380d73ac03b662e4..60ee076bc20a16a48d6d87a47e2995ec86731fb9 100644 --- a/README_EN.md +++ b/README.en.md @@ -44,9 +44,9 @@ The first card in this example uses three events: router, call, and message, as 5. Set the **scheduledUpdateTime** field in the **src/main/resources/base/profile/form_config.json** file to a time point. The widget information is updated at the specified time point. **Second Card** -1. After installing the application, the homepage of the application displays a slideshow of images, and the heart-shaped image in the bottom right corner supports clicking. +1. After installing the application, the homepage of the application displays a list of images and text, and the heart-shaped icon in the upper right corner supports clicking. 2. Long press the application image to select create a second card, click on the card to pull up the application. -3. Select the image and click the heart-shaped button to return to the desktop. The image and heart-shaped status information will be updated to the card. +3. Select the same data displayed on the card within the application, click the heart-shaped button, return to the desktop, and update the heart-shaped status to the card. 4. Configure the **updateDuration** field in the **src/main/resources/base/profile/form_config.json** file. The update cycle unit for card scheduled refresh is 30 minutes. The example configuration is set to 1, which means that after any update of the card, it will be refreshed at a scheduled time after 30 minutes. ### How to Implement @@ -66,6 +66,6 @@ The first card in this example uses three events: router, call, and message, as ### Constraints 1. The sample app is supported only on Huawei phones running the standard system. -2. The HarmonyOS version must be HarmonyOS NEXT Release or later. -3. The DevEco Studio version must be DevEco Studio NEXT Release or later. -4. The HarmonyOS SDK version must be HarmonyOS NEXT Release or later. +2. The HarmonyOS version must be HarmonyOS 5.0.0 Release or later. +3. The DevEco Studio version must be DevEco Studio 5.0.0 Release or later. +4. The HarmonyOS SDK version must be HarmonyOS 5.0.0 Release or later. diff --git a/README.md b/README.md index 1c4ef08f3ffc742fbb63dcd74c5ce9dc4a9ed96a..db64cc76fe814a529ba32ef490ea184f9e123a59 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -# 卡片更新 +# 实现卡片更新与数据交互功能 ### 介绍 -本示例卡片一使用router、call和message三种事件,以及定点刷新的方式实现刷新卡片信息,卡片二实现了定时刷新卡片、应用侧触发刷新卡片的功能。 +服务卡片给用户提供一目了然的信息内容,具有易用可见、智能可选和多段可变的特点。本示例通过卡片开发服务(Form Kit),介绍卡片的创建、交互、更新与管理等功能的实现,使开发者能够高效完成个性化服务卡片的开发。 ### 效果预览 | 第一卡片 | 第二卡片 | @@ -10,11 +10,29 @@ | ![](screenshots/device/form.png) | ![](screenshots/device/form_second.png) | +### 使用说明 + +**卡片一** +1. 安装应用后,长按应用图标,添加服务卡片。 +2. 点击“router事件”按钮进入应用页面,返回桌面时可见卡片信息刷新。 +3. 点击“call事件”,可见卡片信息刷新。 +4. 点击“message事件”可见卡片信息刷新。 +5. 配置“src/main/resources/base/profile/form_config.json”文件中的“scheduledUpdateTime”字段为某个时间,卡片信息即可在相应时间刷新。 + +**卡片二** +1. 安装应用后,应用首页展示图文列表,右上角心形支持点击。 +2. 长按应用图片选择创建卡片二,点击卡片拉起应用。 +3. 应用内选择卡片展示的同一条数据,点击心形按钮,返回桌面,心形状态更新至卡片。 +4. 配置“src/main/resources/base/profile/form_config.json”文件中的“updateDuration”字段。卡片定时刷新的更新周期单位为30分钟。示例配置为1,表示卡片任意更新后,30分钟后定时刷新。 + ### 工程目录 ``` ├──entry/src/main/ets // 代码区 │ ├──common +│ │ ├──utils +│ │ │ ├──Logger.ets // 日志工具类 +│ │ │ └──PreferencesUtil.ets // 首选项工具类 │ │ ├──CommonConstants.ets // 卡片数据 │ │ └──CommonData.ets // 卡片数据工具类 │ ├──entryability @@ -25,40 +43,23 @@ │ │ └──EntryFormAbility.ets // 卡片生命周期类 │ ├──pages │ │ └──Index.ets // 首页 -│ ├──widget -│ │ ├──pages -│ │ │ └──WidgetCard.ets // 卡片一页面 -│ │ ├──view -│ │ │ └──CardListComponent.ets -│ │ └──viewmodel -│ │ └──CardListParameter.ets -│ └──widgetupdate -│ └──pages -│ └──WidgetCardUpdate.ets // 卡片二页面 +│ └──widget +│ ├──pages +│ │ ├──WidgetCard.ets // 卡片一页面 +│ │ └──WidgetCardUpdate.ets // 卡片二页面 +│ ├──view +│ │ └──CardListComponent.ets +│ └──viewmodel +│ └──CardListParameter.ets └──entry/src/main/resources // 应用静态资源目录 ``` -### 使用说明 - -**第一卡片** -1. 安装应用后,长按应用图标,添加服务卡片。 -2. 点击“router事件”按钮进入应用页面,返回桌面时可见卡片信息刷新。 -3. 点击“call事件”,可见卡片信息刷新。 -4. 点击“message事件”可见卡片信息刷新。 -5. 配置“src/main/resources/base/profile/form_config.json”文件中的“scheduledUpdateTime”字段为某个时间,卡片信息即可在相应时间刷新。 - -**第二卡片** -1. 安装应用后,应用首页展示图片轮播图,右下角心形支持点击。 -2. 长按应用图片选择创建第二卡片,点击卡片拉起应用。 -3. 选择图片点击心形按钮,返回桌面,图片及心形状态信息更新至卡片。 -4. 配置“src/main/resources/base/profile/form_config.json”文件中的“updateDuration”字段。卡片定时刷新的更新周期单位为30分钟。示例配置为1,表示卡片任意更新后,30分钟后定时刷新。 - ### 实现说明 1. router事件通过应用EntryAbility的生命周期回调触发更新方法,使用formProvider的updateForm方法,将内容更新到指定卡片。 2. call事件在EntryFormAbility的onAddForm中更新卡片信息,触发卡片UI的onFormTimeChange方法,通过其中postCardAction方法携带的updateCardInfo信息,触发EntryAbility中的callee监听,在监听方法中进行刷新处理。 3. message事件在EntryFormAbility的onFormEvent回调中进行刷新处理。 -4. 第二卡片创建后使用call事件将卡片id传递至EntryAbility后保存至首选项,应用侧从首选项获取卡片id使用updateForm方法更新指定卡片。 +4. 卡片二创建后使用call事件将卡片id传递至EntryAbility后保存至首选项,应用侧从首选项获取卡片id使用updateForm方法更新指定卡片。 #### 注: 1. 本项目的卡片中信息为代码中配置的数据,在真实场景中,可以自行封装获取信息的方法。 @@ -70,6 +71,6 @@ ohos.permission.KEEP_BACKGROUND_RUNNING:允许Service Ability在后台持续 ### 约束与限制 1. 本示例仅支持标准系统上运行,支持设备:华为手机。 -2. HarmonyOS系统:HarmonyOS NEXT Release及以上。 -3. DevEco Studio版本:DevEco Studio NEXT Release及以上。 -4. HarmonyOS SDK版本:HarmonyOS NEXT Release SDK及以上。 \ No newline at end of file +2. HarmonyOS系统:HarmonyOS 5.0.0 Release及以上。 +3. DevEco Studio版本:DevEco Studio 5.0.0 Release及以上。 +4. HarmonyOS SDK版本:HarmonyOS 5.0.0 Release SDK及以上。 \ No newline at end of file diff --git a/entry/src/main/ets/common/CommonConstants.ets b/entry/src/main/ets/common/CommonConstants.ets index 63fa82a911ea99a454abf8b07cef6a03737a7676..f0ee7dca6041f7a1165329136ab7ac2d3b6a0e90 100644 --- a/entry/src/main/ets/common/CommonConstants.ets +++ b/entry/src/main/ets/common/CommonConstants.ets @@ -18,82 +18,106 @@ import { CardListItemData } from './CommonData'; export class CommonConstants { static readonly CARD_LIST_DATA_FIRST: Array = [ { - id: 1, + id: 0, title: $r('app.string.title1'), content: $r('app.string.content1'), - icon: $r('app.media.item1') + icon: $r('app.media.item1'), + favour: false, + bgImage: $r('app.media.ic_picture1') }, { - id: 2, + id: 1, title: $r('app.string.title2'), content: $r('app.string.content2'), - icon: $r('app.media.item2') + icon: $r('app.media.item2'), + favour: false, + bgImage: $r('app.media.ic_picture2') }, { - id: 3, + id: 2, title: $r('app.string.title3'), content: $r('app.string.content3'), - icon: $r('app.media.item3') + icon: $r('app.media.item3'), + favour: false, + bgImage: $r('app.media.ic_picture3') }, { - id: 4, + id: 3, title: $r('app.string.title4'), content: $r('app.string.content4'), - icon: $r('app.media.item4') + icon: $r('app.media.item4'), + favour: false, + bgImage: $r('app.media.ic_picture4') } ]; static readonly CARD_LIST_DATA_SECOND: Array = [ { - id: 1, + id: 4, title: $r('app.string.title5'), content: $r('app.string.content5'), - icon: $r('app.media.item5') + icon: $r('app.media.item5'), + favour: false, + bgImage: $r('app.media.ic_picture5') }, { - id: 2, + id: 5, title: $r('app.string.title6'), content: $r('app.string.content6'), - icon: $r('app.media.item6') + icon: $r('app.media.item6'), + favour: false, + bgImage: $r('app.media.ic_picture6') }, { - id: 3, + id: 6, title: $r('app.string.title7'), content: $r('app.string.content7'), - icon: $r('app.media.item7') + icon: $r('app.media.item7'), + favour: false, + bgImage: $r('app.media.ic_picture7') }, { - id: 4, + id: 7, title: $r('app.string.title8'), content: $r('app.string.content8'), - icon: $r('app.media.item8') + icon: $r('app.media.item8'), + favour: false, + bgImage: $r('app.media.ic_picture8') } ]; static readonly CARD_LIST_DATA_THIRD: Array = [ { - id: 1, + id: 8, title: $r('app.string.title9'), content: $r('app.string.content9'), - icon: $r('app.media.item9') + icon: $r('app.media.item9'), + favour: false, + bgImage: $r('app.media.ic_picture9') }, { - id: 2, + id: 9, title: $r('app.string.title10'), content: $r('app.string.content10'), - icon: $r('app.media.item10') + icon: $r('app.media.item10'), + favour: false, + bgImage: $r('app.media.ic_picture10') }, { - id: 3, + id: 10, title: $r('app.string.title11'), content: $r('app.string.content11'), - icon: $r('app.media.item11') + icon: $r('app.media.item11'), + favour: false, + bgImage: $r('app.media.ic_picture11') }, { - id: 4, + id: 11, title: $r('app.string.title12'), content: $r('app.string.content12'), - icon: $r('app.media.item12') + icon: $r('app.media.item12'), + favour: false, + bgImage: $r('app.media.ic_picture12') } ]; } \ No newline at end of file diff --git a/entry/src/main/ets/common/CommonData.ets b/entry/src/main/ets/common/CommonData.ets index e0d82376b30985101419296f7aa0a5226eb52833..a77c95f9793dd336b957e3a59495e0ff3d32f4bd 100644 --- a/entry/src/main/ets/common/CommonData.ets +++ b/entry/src/main/ets/common/CommonData.ets @@ -19,9 +19,9 @@ export class CommonData { static flag: number = 0; static getData(): Array { - if (CommonData.flag % 3 === 0) { + if (CommonData.flag === 0) { return CommonConstants.CARD_LIST_DATA_FIRST; - } else if (CommonData.flag % 3 === 1) { + } else if (CommonData.flag === 1) { return CommonConstants.CARD_LIST_DATA_SECOND; } else { return CommonConstants.CARD_LIST_DATA_THIRD; @@ -29,23 +29,22 @@ export class CommonData { } static changeFlag(): void { - CommonData.flag++; + CommonData.flag = (CommonData.flag + 1) % 3; } } - export interface CardListItemData { id: number; title: ResourceStr; content: ResourceStr; - icon?: Resource; - favour?: boolean; + icon: Resource; + favour: boolean; + bgImage: Resource; } export class FormData { formId: string = ''; formTime: string = ''; - imageItem?: ImageItem = undefined; isFavor?: boolean = false; index?: number = 0; cardList: Array = []; @@ -53,17 +52,4 @@ export class FormData { constructor(formId: string) { this.formId = formId; } -} - -@Observed -export class ImageItem { - public id: number = 0; - public image: ResourceStr = ''; - public isFavor: boolean = false; - - constructor(id: number, image: ResourceStr, isFavor: boolean) { - this.id = id; - this.image = image; - this.isFavor = isFavor - } } \ No newline at end of file diff --git a/entry/src/main/ets/common/utils/Logger.ets b/entry/src/main/ets/common/utils/Logger.ets new file mode 100644 index 0000000000000000000000000000000000000000..53812d95f6340743f4e24918128ce5d782a4e332 --- /dev/null +++ b/entry/src/main/ets/common/utils/Logger.ets @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; + +class Logger { + private domain: number; + private prefix: string; + private format: string = '%{public}s, %{public}s'; + + /** + * Constructor. + * + * @param Prefix Identifies the log tag. + * @param domain Domain Indicates the service domain, which is a hexadecimal integer ranging from 0x0 to 0xFFFFF. + */ + constructor(prefix: string) { + this.prefix = prefix; + this.domain = 0xFF00; + } + + debug(...args: string[]): void { + hilog.debug(this.domain, this.prefix, this.format, args); + } + + info(...args: string[]): void { + hilog.info(this.domain, this.prefix, this.format, args); + } + + warn(...args: string[]): void { + hilog.warn(this.domain, this.prefix, this.format, args); + } + + error(...args: string[]): void { + hilog.error(this.domain, this.prefix, this.format, args); + } +} + +export default new Logger('CardInfoRefresh'); \ No newline at end of file diff --git a/entry/src/main/ets/common/utils/PreferencesUtil.ets b/entry/src/main/ets/common/utils/PreferencesUtil.ets new file mode 100644 index 0000000000000000000000000000000000000000..88269eb5aff92d6d9726b449fd4d21b1345d713b --- /dev/null +++ b/entry/src/main/ets/common/utils/PreferencesUtil.ets @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { preferences } from '@kit.ArkData'; +import { CardListItemData } from '../CommonData'; +import { CommonConstants } from '../CommonConstants'; +import Logger from './Logger'; + +const TAG: string = 'PreferencesUtil'; +const MY_STORE: string = 'myStore'; + +export class PreferencesUtil { + private static preferencesUtil: PreferencesUtil; + + public static getInstance(): PreferencesUtil { + if (!PreferencesUtil.preferencesUtil) { + PreferencesUtil.preferencesUtil = new PreferencesUtil(); + } + return PreferencesUtil.preferencesUtil; + } + + getPreferences(context: Context): preferences.Preferences { + preferences.removePreferencesFromCacheSync(context, MY_STORE); + return preferences.getPreferencesSync(context, { name: MY_STORE }); + } + + preferencesFlush(preferences: preferences.Preferences) { + preferences.flush((err) => { + if (err) { + Logger.error(TAG, `Failed to flush. Code:${err.code}, message:${err.message}`); + } + }) + } + + preferencesPut(preferences: preferences.Preferences, key: string, value: preferences.ValueType): void { + preferences.putSync(key, value); + this.preferencesFlush(preferences); + } + + removePreferencesFromCache(context: Context): void { + preferences.removePreferencesFromCache(context, MY_STORE); + } + + getFormIds(preferences: preferences.Preferences): Array { + if (preferences === null) { + Logger.error(TAG, `preferences is null`); + return []; + } + return preferences.getSync('formIdList', ['']) as Array; + } + + addFormId(preferences: preferences.Preferences, formId: string): void { + try { + if (preferences.hasSync('formIdList')) { + let formIds = this.getFormIds(preferences); + if (formIds.indexOf(formId) === -1) { + formIds.push(formId); + this.preferencesPut(preferences, 'formIdList', formIds); + } + } else { + this.preferencesPut(preferences, 'formIdList', [formId]); + } + this.preferencesFlush(preferences); + } catch (error) { + Logger.error(TAG, `Failed to check the key 'formIds'. Code:${error.code}, message:${error.message}`); + } + } + + getFormInitData(key: string, preferences: preferences.Preferences): CardListItemData { + let initData: CardListItemData = CommonConstants.CARD_LIST_DATA_FIRST[0]; + let index: number = preferences.getSync(key, 0) as number; + + if (preferences.hasSync(`dataArr`)) { + initData = (preferences.getSync(`dataArr`, []) as CardListItemData[])[index]; + initData.favour = (preferences.getSync(`statusArr`, []) as boolean[])[index]; + } + return initData; + } + + removeFormId(context: Context, formId: string) { + try { + let preferences = this.getPreferences(context); + if (preferences === null) { + Logger.error(TAG, `preferences is null`); + return; + } + if (preferences.hasSync('formIdList')) { + let formIds = this.getFormIds(preferences); + let index = formIds.indexOf(formId); + if (index !== -1) { + formIds.splice(index, 1); + } + this.preferencesPut(preferences, 'formIdList', formIds); + if (preferences.hasSync(`${formId}_show_index`)) { + preferences.deleteSync(`${formId}_show_index`); + } + this.preferencesFlush(preferences); + } + } catch (error) { + Logger.error(TAG, `Failed to get preferences. Code:${error.code}, message:${error.message}`); + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets index d6c45f0e000c155cc84f5c7f993c8feaf164296c..8eba40ade4fc38f73a18fac0fd0b7ef3225f2b8b 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ets +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -14,12 +14,14 @@ */ import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; -import { preferences } from '@kit.ArkData'; import { window } from '@kit.ArkUI'; -import { rpc } from '@kit.IPCKit'; import { formBindingData, formInfo, formProvider } from '@kit.FormKit'; +import { rpc } from '@kit.IPCKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; -import { CommonData, FormData, ImageItem } from '../common/CommonData'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { CardListItemData, CommonData, FormData } from '../common/CommonData'; +import { PreferencesUtil } from '../common/utils/PreferencesUtil'; +import { CommonConstants } from '../common/CommonConstants'; const TAG: string = 'EntryAbility'; @@ -31,50 +33,96 @@ export default class EntryAbility extends UIAbility { let formData = new FormData(formId); formData.cardList = CommonData.getData(); CommonData.changeFlag(); - this.updateFormData(formId, formData); + let formMsg: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); + formProvider.updateForm(formId, formMsg).then((data) => { + hilog.info(0x0000, TAG, 'updateForm success.', JSON.stringify(data)); + }).catch((error: Error) => { + hilog.info(0x0000, TAG, 'updateForm failed.', JSON.stringify(error)); + }); } return new MyParcelable(1); }; - private callSaveFunc = (data: rpc.MessageSequence): MyParcelable => { + private callUpdateFunc = (data: rpc.MessageSequence): MyParcelable => { let params: Record = JSON.parse(data.readString()); if (params.formId !== undefined) { - let formId: string = params.formId; - let index: number = Number.parseInt(params.index); - let formData = new FormData(formId); - let formIdArr: Array = []; - let myPreferences = AppStorage.get('myPreferences') as preferences.Preferences; - if (myPreferences.hasSync('favorCardId')) { - formIdArr = myPreferences.getSync('favorCardId', []) as Array; + let index: number = Number.parseInt(params.msgId); + + let util = PreferencesUtil.getInstance(); + let preferences = util.getPreferences(this.context); + let dataItem: CardListItemData = (preferences.getSync('dataArr', []) as CardListItemData[])[index]; + let statusArr: boolean[] = preferences.getSync('statusArr', []) as boolean[]; + if (statusArr.length === 0) { + statusArr = new Array(12).fill(false); } - formIdArr.push(formId); - myPreferences.putSync('favorCardId', formIdArr); - myPreferences.flush(); - let imageArr: ImageItem[] = myPreferences.getSync('imageArr', []) as ImageItem[]; - if (imageArr.length > 0) { - formData.imageItem = imageArr[index + 1 % 3]; - formData.isFavor = imageArr[index + 1 % 3].isFavor; - formData.index = imageArr[index + 1 % 3].id; + statusArr[index] = !statusArr[index]; + dataItem.favour = statusArr[index]; + + preferences.putSync('statusArr', statusArr); + preferences.flush(() => { + AppStorage.setOrCreate('statusArr', [...statusArr]); + }); + + let idArr = PreferencesUtil.getInstance().getFormIds(preferences); + if (idArr.length > 0) { + idArr.forEach((formId: string) => { + if (preferences.getSync(`${formId}_show_index`, -1) as number === index) { + let formData = new FormData(formId); + formData.cardList = [dataItem]; + let formMsg: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); + formProvider.updateForm(formId, formMsg) + .then(() => { + hilog.info(0x0000, TAG, `updateForm success.`); + }) + .catch((error: Error) => { + hilog.error(0x0000, TAG, `updateForm failed: ${JSON.stringify(error)}`); + }); + } + }) } - this.updateFormData(formId, formData); } return new MyParcelable(1); }; - private createPreferences(): void { - let dataPreferences: preferences.Preferences | null = null; - let options: preferences.Options = { - name: 'myStore' - }; - dataPreferences = preferences.getPreferencesSync(this.context, options); - AppStorage.setOrCreate('myPreferences', dataPreferences); - } - onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { hilog.info(0x0000, TAG, '%{public}s', 'Ability onCreate'); - this.createPreferences(); + this.initData(); this.updateInfo(want); this.callee.on('updateCardInfo', this.callFunc); - this.callee.on('saveAndUpdateForm', this.callSaveFunc); + this.callee.on('updateFormFavour', this.callUpdateFunc); + } + + initData(): void { + let util = PreferencesUtil.getInstance(); + let preferences = util.getPreferences(this.context); + let dataArr: CardListItemData[] = []; + let keyDataArr: string = 'dataArr'; + if (!preferences.hasSync(keyDataArr)) { + CommonConstants.CARD_LIST_DATA_FIRST.forEach((item) => { + dataArr.push(item); + }); + CommonConstants.CARD_LIST_DATA_SECOND.forEach((item) => { + dataArr.push(item); + }); + CommonConstants.CARD_LIST_DATA_THIRD.forEach((item) => { + dataArr.push(item); + }); + preferences.putSync('dataArr', dataArr); + } else { + dataArr = preferences.getSync('dataArr', []) as CardListItemData[]; + } + + let statusArr: boolean[] = new Array(12).fill(false); + let keyStatusArr: string = 'statusArr'; + if (!preferences.hasSync(keyStatusArr)) { + preferences.putSync(keyStatusArr, statusArr); + } else { + statusArr = preferences.getSync('statusArr', []) as boolean[]; + } + + preferences.flush(() => { + AppStorage.setOrCreate('dataArr', dataArr); + AppStorage.setOrCreate('statusArr', statusArr); + }) } onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void { @@ -82,28 +130,31 @@ export default class EntryAbility extends UIAbility { } private updateInfo(want: Want) { - if (!want.parameters || want.parameters[formInfo.FormParam.IDENTITY_KEY] === undefined) { + if (!want || !want.parameters || want.parameters[formInfo.FormParam.IDENTITY_KEY] === undefined) { return; } let message: string = (JSON.parse(want.parameters?.params as string))?.message; if (message === 'Router refresh card.') { - this.routerUpdate(want.parameters); + let formId = want.parameters[formInfo.FormParam.IDENTITY_KEY].toString(); + let formData = new FormData(formId); + formData.cardList = CommonData.getData(); + CommonData.changeFlag(); + let formMsg: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); + formProvider.updateForm(formId, formMsg) + .then((data) => { + hilog.info(0x0000, TAG, 'updateForm success.', JSON.stringify(data)); + }) + .catch((error: Error) => { + hilog.info(0x0000, TAG, 'updateForm failed.', JSON.stringify(error)); + }); } } - private routerUpdate(parameters: Record) { - let formId = parameters[formInfo.FormParam.IDENTITY_KEY].toString(); - let formData = new FormData(formId); - formData.cardList = CommonData.getData(); - CommonData.changeFlag(); - this.updateFormData(formId, formData); - } - onDestroy(): void { hilog.info(0x0000, TAG, '%{public}s', 'Ability onDestroy'); try { this.callee.off('updateCardInfo'); - this.callee.off('saveAndUpdateForm'); + this.callee.off('updateFormFavour'); } catch (err) { hilog.error(0x0000, TAG, 'Failed to disconnect callee. Cause: %{public}s', JSON.stringify(err) ?? ''); } @@ -112,6 +163,16 @@ export default class EntryAbility extends UIAbility { onWindowStageCreate(windowStage: window.WindowStage): void { // Main window is created, set main page for this ability hilog.info(0x0000, TAG, '%{public}s', 'Ability onWindowStageCreate'); + windowStage.getMainWindow((error: BusinessError, data) => { + if (error.code) { + hilog.error(0x0000, TAG, 'Failed to get main window. Cause: %{public}s', JSON.stringify(error) ?? ''); + return; + } + data.setWindowLayoutFullScreen(true); + AppStorage.setOrCreate('topHeight', data.getWindowAvoidArea(window.AvoidAreaType.TYPE_SYSTEM).topRect.height); + AppStorage.setOrCreate('bottomHeight', + data.getWindowAvoidArea(window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR).bottomRect.height); + }); windowStage.loadContent('pages/Index', (err) => { if (err.code) { @@ -136,16 +197,6 @@ export default class EntryAbility extends UIAbility { // Ability has back to background hilog.info(0x0000, TAG, '%{public}s', 'Ability onBackground'); } - - - private updateFormData(formId: string, formData: FormData): void { - let formMsg: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); - formProvider.updateForm(formId, formMsg).then((data) => { - hilog.info(0x0000, TAG, 'updateForm success.', JSON.stringify(data)); - }).catch((error: Error) => { - hilog.info(0x0000, TAG, 'updateForm failed.', JSON.stringify(error)); - }); - } } class MyParcelable implements rpc.Parcelable { diff --git a/entry/src/main/ets/entryformability/EntryFormAbility.ets b/entry/src/main/ets/entryformability/EntryFormAbility.ets index 215b665abffdca811deade59e390cee95d11c630..25923ce757f60090c49bfca70237ee17fdbe3871 100644 --- a/entry/src/main/ets/entryformability/EntryFormAbility.ets +++ b/entry/src/main/ets/entryformability/EntryFormAbility.ets @@ -17,47 +17,78 @@ import { Want } from '@kit.AbilityKit'; import { systemDateTime } from '@kit.BasicServicesKit'; import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; -import { CommonData, FormData } from '../common/CommonData'; +import { CardListItemData, CommonData, FormData } from '../common/CommonData'; +import { PreferencesUtil } from '../common/utils/PreferencesUtil'; + +const TAG: string = 'EntryFormAbility'; export default class EntryFormAbility extends FormExtensionAbility { onAddForm(want: Want): formBindingData.FormBindingData { - // Called to return a FormBindingData object. - let formData = ''; - if (want && want.parameters) { - let formName: string = want.parameters['ohos.extra.param.key.form_name'] as string; - let formId: string = want.parameters['ohos.extra.param.key.form_identity'] as string; - console.info('llx_test addForm: ' + formId) - if (formName === 'card_info_refresh' || formName === 'card_info_update') { - let formData = new FormData(formId); - formData.formTime = systemDateTime.getTime().toString(); - let formInfo: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); - formProvider.updateForm(formId, formInfo); - return formInfo; - } + if(!want || !want.parameters) { + hilog.error(0x0000, TAG, `FormAbility onAddForm want or want.parameters is undefined`); + return formBindingData.createFormBindingData(''); + } + + let formName: string = want.parameters[formInfo.FormParam.NAME_KEY] as string; + let formId: string = want.parameters[formInfo.FormParam.IDENTITY_KEY] as string; + let util = PreferencesUtil.getInstance(); + let preferences = util.getPreferences(this.context); + // Save form id using preferences. + util.addFormId(preferences, formId); + + if (formName === 'card_info_refresh') { + let formData = new FormData(formId); + formData.formTime = systemDateTime.getTime().toString(); + let formInfo: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); + return formInfo; + } + + let key: string = `${formId}_show_index`; + let data = util.getFormInitData(key, preferences); + if (formName === 'card_info_update') { + // Save the index of the data items currently displayed on the card. + util.preferencesPut(preferences, key, data.id); + let formData = new FormData(formId); + formData.cardList.push(data); + let formInfo: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); + return formInfo; } - return formBindingData.createFormBindingData(formData); + + return formBindingData.createFormBindingData(''); } onUpdateForm(formId: string) { // Called to notify the form provider to update a specified form. - hilog.info(0x0000, 'testTag', `FormAbility onUpdateForm, formId = ${formId}`); + hilog.info(0x0000, TAG, `FormAbility onUpdateForm, formId = ${formId}`); let formData = new FormData(formId); formData.formTime = systemDateTime.getTime().toString(); + + let util = PreferencesUtil.getInstance(); + let preferences = util.getPreferences(this.context); + let key: string = `${formId}_show_index`; + if (preferences.hasSync(key)) { + let index = preferences.getSync(key, 0) as number; + let newIndex = (index + 1) % 12; + let dataItem: CardListItemData = (preferences.getSync('dataArr', []) as CardListItemData[])[newIndex]; + dataItem.favour = (preferences.getSync('statusArr', []) as boolean[])[newIndex]; + util.preferencesPut(preferences, key, newIndex); + formData.cardList = [dataItem]; + } let formMsg: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); formProvider.updateForm(formId, formMsg); } onFormEvent(formId: string, message: string) { // Called when a specified message event defined by the form provider is triggered. - hilog.info(0x0000, 'testTag', `FormAbility onFormEvent, formId = ${formId}, message: ${JSON.stringify(message)}`); + hilog.info(0x0000, TAG, `FormAbility onFormEvent, formId = ${formId}, message: ${JSON.stringify(message)}`); let formData = new FormData(formId); formData.cardList = CommonData.getData(); CommonData.changeFlag(); let formMsg: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); - formProvider.updateForm(formId, formMsg).then((data) => { - hilog.info(0x0000, 'testTag', 'updateForm success.', JSON.stringify(data)); + formProvider.updateForm(formId, formMsg).then(() => { + hilog.info(0x0000, TAG, 'updateForm success.'); }).catch((error: Error) => { - hilog.info(0x0000, 'testTag', 'updateForm failed.', JSON.stringify(error)); + hilog.error(0x0000, TAG, 'updateForm failed.%s', JSON.stringify(error)); }); } @@ -65,4 +96,9 @@ export default class EntryFormAbility extends FormExtensionAbility { // Called to return a {@link FormState} object. return formInfo.FormState.READY; } + + async onRemoveForm(formId: string): Promise { + hilog.info(0x00, TAG, `remove formId: ${formId}`); + PreferencesUtil.getInstance().removeFormId(this.context, formId); + } } \ No newline at end of file diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index dc32869276758d74911708324f91ae36b77549de..ab29fb4da9ce6954d1104a152b2e0cb66cb4c947 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -13,109 +13,134 @@ * limitations under the License. */ -import { preferences } from '@kit.ArkData'; import { formBindingData, formProvider } from '@kit.FormKit'; import { hilog } from '@kit.PerformanceAnalysisKit'; -import { FormData, ImageItem } from '../common/CommonData'; +import { CommonConstants } from '../common/CommonConstants'; +import { CardListItemData, FormData } from '../common/CommonData'; +import { PreferencesUtil } from '../common/utils/PreferencesUtil'; const TAG: string = 'Index'; @Entry @Component struct Index { - @StorageLink('myPreferences') myPreferences: preferences.Preferences | undefined = undefined; - @StorageLink('imageArr') imageInfoArray: ImageItem[] = [ - new ImageItem(0, $r('app.media.ic_social_circle1'), false), - new ImageItem(1, $r('app.media.ic_social_circle2'), false), - new ImageItem(2, $r('app.media.ic_social_circle3'), false) - ]; - - aboutToAppear(): void { - if (this.myPreferences) { - if (this.myPreferences.hasSync('imageArr')) { - this.imageInfoArray = this.myPreferences.getSync('imageArr', []) as ImageItem[]; - return; - } else { - this.myPreferences?.putSync('imageArr', this.imageInfoArray); - this.myPreferences?.flush(); - } - } - } + @StorageLink('dataArr') dataArr: CardListItemData[] = [...CommonConstants.CARD_LIST_DATA_FIRST]; + @StorageLink('topHeight') topHeight: number = 0; + @StorageLink('bottomHeight') bottomHeight: number = 0; build() { Navigation() { - Swiper() { - ForEach(this.imageInfoArray, (item: ImageItem, index: number) => { - ImageView({ - imageItem: item, - isFavor: item.isFavor, - index: index - }) - .layoutWeight(1) - }, (item: ImageItem) => JSON.stringify(item)) + Scroll() { + Column({ space: 12 }) { + ForEach(this.dataArr, (item: CardListItemData, index: number) => { + DataItemView({ itemData: item }) + .margin({ bottom: index === this.dataArr.length - 1 ? px2vp(this.bottomHeight) : 0 }) + }, (item: CardListItemData, index: number) => index + JSON.stringify(item)) + } } - .width('100%') - .borderRadius(24) + .scrollBar(BarState.Off) + .padding({ + left: 16, + right: 16 + }) } .mode(NavigationMode.Stack) .title($r('app.string.EntryAbility_label')) - .height('100%') + .titleMode(NavigationTitleMode.Mini) + .hideBackButton(true) .width('100%') - .margin({ - top: 16 - }) - .padding({ - left: 16, - right: 16 - }) + .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM]) + .backgroundColor('#F1F3F5') + .padding({ top: px2vp(this.topHeight) }) } } @Component -struct ImageView { - @StorageLink('myPreferences') myPreferences: preferences.Preferences | undefined = undefined; - @ObjectLink imageItem: ImageItem; - @State isFavor: boolean = false; - index: number = 0; +struct DataItemView { + @Prop itemData: CardListItemData; + @StorageLink('statusArr') statusArr: boolean[] = []; build() { - Stack() { - Image(this.imageItem.image) - .objectFit(ImageFit.Auto) - .width('100%') - .height('33%') + Column() { + Row({ space: 12 }) { + Column({ space: 4 }) { + Text(this.itemData.title) + .maxLines(1) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + .fontSize(16) + .fontWeight(700) + .lineHeight(21) + .letterSpacing(0) + .fontColor(Color.Black) + .height(21) + Text(this.itemData.content) + .maxLines(2) + .fontSize(12) + .lineHeight(16) + .letterSpacing(0) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + .fontWeight(FontWeight.Regular) + .height(35) + .fontColor($r('sys.color.mask_secondary')) + } + .alignItems(HorizontalAlign.Start) + .justifyContent(FlexAlign.Center) + .layoutWeight(1) - Image(this.isFavor ? $r('app.media.ic_public_favor_filled') : $r('app.media.ic_public_favor')) - .height(30) - .aspectRatio(1) - .margin({ - right: 8, - bottom: 8 - }) + Row() { + if (!this.statusArr[this.itemData.id!]) { + SymbolGlyph($r('sys.symbol.heart')) + .fontSize(24) + .aspectRatio(1) + } else { + SymbolGlyph($r('sys.symbol.heart_fill')) + .fontSize(24) + .aspectRatio(1) + .fontColor(['#E64566']) + } + } .onClick(() => { - this.isFavor = !this.isFavor; - this.imageItem.isFavor = this.isFavor; - let tmpArr = this.myPreferences?.getSync('imageArr', []) as ImageItem[]; - tmpArr[this.index] = this.imageItem; - this.myPreferences?.putSync('imageArr', tmpArr); - this.myPreferences?.flush(); + let util = PreferencesUtil.getInstance(); + let preferences = util.getPreferences(getContext(this)); + this.statusArr[this.itemData.id] = !this.statusArr[this.itemData.id]; + this.itemData.favour = this.statusArr[this.itemData.id!]; + util.preferencesPut(preferences, 'statusArr', this.statusArr); + + // Update page display data. + AppStorage.set('statusArr', [...this.statusArr]); - let favorCardIdArr = this.myPreferences?.getSync('favorCardId', '') as Array; - if (favorCardIdArr.length > 0) { - favorCardIdArr.forEach((fromId: string) => { - let formData = new FormData(fromId); - formData.imageItem = this.imageItem; - formData.isFavor = this.isFavor; - let formMsg: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); - formProvider.updateForm(fromId, formMsg).then((data) => { - hilog.info(0x0000, TAG, `updateForm success. ${JSON.stringify(data)}`); - }).catch((error: Error) => { - hilog.error(0x0000, TAG, `updateForm failed: ${JSON.stringify(error)}`); - }); + let idArr = PreferencesUtil.getInstance().getFormIds(preferences); + if (idArr.length > 0) { + idArr.forEach((formId: string) => { + if (preferences.getSync(`${formId}_show_index`, -1) as number === this.itemData.id) { + let formData = new FormData(formId); + formData.cardList = [this.itemData]; + let formMsg: formBindingData.FormBindingData = formBindingData.createFormBindingData(formData); + formProvider.updateForm(formId, formMsg).then(() => { + hilog.info(0x0000, TAG, `updateForm success.`); + }).catch((error: Error) => { + hilog.error(0x0000, TAG, `updateForm failed: ${JSON.stringify(error)}`); + }); + } }) } }) + } + .alignItems(VerticalAlign.Top) + .width('100%') + + Blank() + .height(12) + Image(this.itemData.bgImage) + .width('100%') + .aspectRatio(16 / 9) + .objectFit(ImageFit.Cover) + .autoResize(true) + .borderRadius(10) } - .alignContent(Alignment.BottomEnd) + .width('100%') + .backgroundColor(Color.White) + .borderRadius(15) + .padding(12) } } \ No newline at end of file diff --git a/entry/src/main/ets/widget/pages/WidgetCard.ets b/entry/src/main/ets/widget/pages/WidgetCard.ets index 77595e0ca5821774fa3b3b0600b2604d0f3c65ca..e7af546e84a41c9429499eeb5969ed6a6db45745 100644 --- a/entry/src/main/ets/widget/pages/WidgetCard.ets +++ b/entry/src/main/ets/widget/pages/WidgetCard.ets @@ -15,13 +15,20 @@ import { CardListComponent } from '../view/CardListComponent'; import { CardListParameter } from '../viewmodel/CardListParameter'; -import { CardListItemData } from '../../common/CommonData' +import { CardListItemData } from '../../common/CommonData'; -let storageUpdate = new LocalStorage(); +let storageLocal = new LocalStorage(); -@Entry(storageUpdate) +@Entry(storageLocal) @Component struct WidgetCard { + @LocalStorageProp('formTime') @Watch('onFormTimeChange') formTime: string = ''; + @LocalStorageProp('cardList') cardList: Array = []; + @LocalStorageProp('formId') formId: string = ''; + @State cardListParameter: CardListParameter = new CardListParameter($r('sys.color.ohos_id_color_background'), + $r('app.string.card_list_title'), '', ImageSize.Cover, $r('app.media.logo'), false, + $r('sys.color.ohos_id_color_background'), true, this.cardList.length, $r('sys.color.ohos_id_color_emphasize'), + $r('app.color.list_item_count_background'), '', false); /* * The action type. */ @@ -42,13 +49,6 @@ struct WidgetCard { * The height percentage setting. */ readonly FULL_HEIGHT_PERCENT: string = '100%'; - @LocalStorageProp('formTime') @Watch('onFormTimeChange') formTime: string = ''; - @LocalStorageProp('cardList') cardList: Array = []; - @LocalStorageProp('formId') formId: string = ''; - @State cardListParameter: CardListParameter = new CardListParameter($r('sys.color.ohos_id_color_background'), - $r('app.string.card_list_title'), '', ImageSize.Cover, $r('app.media.logo'), false, - $r('sys.color.ohos_id_color_background'), true, this.cardList.length, $r('sys.color.ohos_id_color_emphasize'), - $r('app.color.list_item_count_background'), '', false); onFormTimeChange() { postCardAction(this, { @@ -63,7 +63,7 @@ struct WidgetCard { } @Builder - buttonBuilder(text: ResourceStr, action: string, message: string, method?: string) { + buttonBuilder(text: ResourceStr) { Column() { Image($r('app.media.refresh')) .width($r('app.float.refresh_image_size')) @@ -79,17 +79,6 @@ struct WidgetCard { .width($r('app.float.refresh_area_width')) .borderRadius($r('app.float.border_radius')) .backgroundColor($r('sys.color.comp_background_focus')) - .onClick(() => { - postCardAction(this, { - action: action, - abilityName: 'EntryAbility', - params: { - formId: this.formId, - method: method, - message: message - } - }); - }) } @Builder @@ -136,15 +125,51 @@ struct WidgetCard { } .width(this.FULL_WIDTH_PERCENT) .height($r('app.float.item_height')) - }, (item: number, index) => index + JSON.stringify(item)) + }, (item: CardListItemData, index) => index + JSON.stringify(item)) } Row() { - this.buttonBuilder($r('app.string.router'), 'router', 'Router refresh card.') + Row(){ + this.buttonBuilder($r('app.string.router')) + } + .onClick(() => { + postCardAction(this, { + action: 'router', + abilityName: 'EntryAbility', + params: { + message: 'Router refresh card.' + } + }); + }) - this.buttonBuilder($r('app.string.call'), 'call', 'Call refresh card.', 'updateCardInfo') + Row() { + this.buttonBuilder($r('app.string.call')) + } + .onClick(() => { + postCardAction(this, { + action: 'call', + abilityName: 'EntryAbility', + params: { + formId: this.formId, + method: 'updateCardInfo', + params: { + message: 'Call refresh card.' + } + } + }); + }) - this.buttonBuilder($r('app.string.message'), 'message', 'Message refresh card.') + Row() { + this.buttonBuilder($r('app.string.message')) + } + .onClick(() => { + postCardAction(this, { + action: 'message', + params: { + message: 'Message refresh card.' + } + }); + }) } .width(this.FULL_WIDTH_PERCENT) .justifyContent(FlexAlign.SpaceBetween) diff --git a/entry/src/main/ets/widgetupdate/pages/WidgetCardUpdate.ets b/entry/src/main/ets/widget/pages/WidgetCardUpdate.ets similarity index 40% rename from entry/src/main/ets/widgetupdate/pages/WidgetCardUpdate.ets rename to entry/src/main/ets/widget/pages/WidgetCardUpdate.ets index 9ed4bc562e27967e71fc52a5863571940b8c3c5e..f238d5de729502a2bd723733c8f21707f6e9b68c 100644 --- a/entry/src/main/ets/widgetupdate/pages/WidgetCardUpdate.ets +++ b/entry/src/main/ets/widget/pages/WidgetCardUpdate.ets @@ -13,7 +13,8 @@ * limitations under the License. */ -import { ImageItem } from '../../common/CommonData'; +import { CommonConstants } from '../../common/CommonConstants'; +import { CardListItemData } from '../../common/CommonData'; let localStorage = new LocalStorage(); @@ -21,10 +22,7 @@ let localStorage = new LocalStorage(); @Component struct Widget1Card { @LocalStorageProp('formId') formId: string = ''; - @LocalStorageProp('formTime') @Watch('onFormTimeChange') formTime: string = ''; - @LocalStorageProp('imageItem') imageItem: ImageItem = new ImageItem(0, $r('app.media.ic_social_circle1'), false); - @LocalStorageProp('isFavor') isFavor: boolean = false; - @LocalStorageProp('index') index: number = -1; + @LocalStorageProp('cardList') itemData: CardListItemData[] = [CommonConstants.CARD_LIST_DATA_FIRST[0]]; /* * The action type. */ @@ -37,45 +35,72 @@ struct Widget1Card { * The message. */ readonly MESSAGE: string = 'add detail'; - /* - * The width percentage setting. - */ - readonly FULL_WIDTH_PERCENT: string = '100%'; /* * The height percentage setting. */ readonly FULL_HEIGHT_PERCENT: string = '100%'; - onFormTimeChange() { - if (this.formTime) { - postCardAction(this, { - action: 'call', - abilityName: 'EntryAbility', - params: { - formId: this.formId, - method: 'saveAndUpdateForm', - message: 'Call refresh card.', - index: this.index - } - }); - } - } - build() { - Stack() { - Image(this.imageItem?.image) - .height(this.FULL_WIDTH_PERCENT) - .width(this.FULL_WIDTH_PERCENT) - Image(this.isFavor ? $r('app.media.ic_public_favor_filled') : $r('app.media.ic_public_favor')) - .height(30) - .aspectRatio(1) + Column() { + Text(this.itemData[0].title) + .maxLines(1) + .fontColor(Color.White) + .fontSize(18) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + .fontWeight(FontWeight.Bold) .margin({ - right: 8, - bottom: 8 + left: 12, + top: 12, + right: 12 }) + Blank() + Row({ space: 12 }) { + Text(this.itemData[0].content) + .layoutWeight(1) + .maxLines(2) + .fontColor(Color.White) + .fontSize(14) + .lineHeight(19) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + + Row(){ + if (!this.itemData[0].favour) { + SymbolGlyph($r('sys.symbol.heart')) + .fontSize(24) + .aspectRatio(1) + .fontColor([Color.White]) + } else { + SymbolGlyph($r('sys.symbol.heart_fill')) + .fontSize(24) + .aspectRatio(1) + .fontColor(['#E64566']) + } + } + .height(26) + .aspectRatio(1) + .onClick(() => { + postCardAction(this, { + action: 'call', + abilityName: 'EntryAbility', + params: { + formId: this.formId, + msgId: this.itemData[0].id, + method: 'updateFormFavour', + message: 'Call refresh card.' + } + }); + }) + } + .backgroundBlurStyle(BlurStyle.BACKGROUND_THIN) + .height(56) + .alignItems(VerticalAlign.Bottom) + .padding({ + top: 6, + left: 12, + right: 12, + bottom: 12 + }) } - .alignContent(Alignment.BottomEnd) - .height(this.FULL_HEIGHT_PERCENT) .onClick(() => { postCardAction(this, { action: this.ACTION_TYPE, @@ -85,5 +110,10 @@ struct Widget1Card { } }); }) + .alignItems(HorizontalAlign.Start) + .width('100%') + .height('100%') + .backgroundImage(this.itemData[0].bgImage) + .backgroundImageSize(ImageSize.Cover) } } \ No newline at end of file diff --git a/entry/src/main/ets/widget/view/CardListComponent.ets b/entry/src/main/ets/widget/view/CardListComponent.ets index 5d508ef3c85f2867f8c5f1a8d30f45bb7078b296..f06917aba41ed1a2a1636df7efcc40cd2ec58e81 100644 --- a/entry/src/main/ets/widget/view/CardListComponent.ets +++ b/entry/src/main/ets/widget/view/CardListComponent.ets @@ -17,6 +17,8 @@ import { CardListParameter } from '../viewmodel/CardListParameter'; @Component export struct CardListComponent { + @BuilderParam customBuilderParam: () => void = this.customBuilder; + @Link cardListParameter: CardListParameter; /** * The max quantity of list items. */ @@ -29,8 +31,6 @@ export struct CardListComponent { * The height percentage setting. */ readonly FULL_HEIGHT_PERCENT: string = '100%'; - @BuilderParam customBuilderParam: () => void = this.customBuilder; - @Link cardListParameter: CardListParameter; @Builder customBuilder() { @@ -53,7 +53,7 @@ export struct CardListComponent { if (this.cardListParameter.isItemCount && this.cardListParameter.itemCount) { Text(this.cardListParameter.itemCount > this.MAX_QUANTITY ? '99+' : - this.cardListParameter.itemCount + '') + this.cardListParameter.itemCount.toString()) .textAlign(TextAlign.Center) .fontSize($r('app.float.item_count_font_size')) .fontWeight(FontWeight.Medium) diff --git a/entry/src/main/resources/base/element/string.json b/entry/src/main/resources/base/element/string.json index d517db9c5e9b0d6cbe005404ad82ab20bc2e90f6..4025826c45fdd03ceb42a2128b79999cb6ed8fd0 100644 --- a/entry/src/main/resources/base/element/string.json +++ b/entry/src/main/resources/base/element/string.json @@ -22,11 +22,11 @@ }, { "name": "widget_desc", - "value": "This is a service widget." + "value": "Example of recommended content list." }, { "name": "widget_display_name", - "value": "widget" + "value": "Card Example One" }, { "name": "card_list_title", @@ -150,11 +150,11 @@ }, { "name": "widget1_desc", - "value": "This is a service widget." + "value": "Recommended content examples." }, { "name": "widget1_display_name", - "value": "widget1" + "value": "Card Example Two" } ] } \ No newline at end of file diff --git a/entry/src/main/resources/base/media/ic_picture1.jpg b/entry/src/main/resources/base/media/ic_picture1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fbecb734e29cf780c9031c1cd5dbf058b49726e7 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture1.jpg differ diff --git a/entry/src/main/resources/base/media/ic_picture10.jpg b/entry/src/main/resources/base/media/ic_picture10.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0dcd3cf0e048a713b5822c7276e2834e06c2b83b Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture10.jpg differ diff --git a/entry/src/main/resources/base/media/ic_picture11.jpg b/entry/src/main/resources/base/media/ic_picture11.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1792203c69f1aa2f2cc9e28d8922cf6a860b4aa3 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture11.jpg differ diff --git a/entry/src/main/resources/base/media/ic_picture12.jpg b/entry/src/main/resources/base/media/ic_picture12.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3084c9c0d1469aa595a428e4681067554fba4dec Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture12.jpg differ diff --git a/entry/src/main/resources/base/media/ic_picture2.jpg b/entry/src/main/resources/base/media/ic_picture2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2781c6f20dfe3b11e0771ef9667db291aeea6a7c Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture2.jpg differ diff --git a/entry/src/main/resources/base/media/ic_picture3.jpg b/entry/src/main/resources/base/media/ic_picture3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3ba44b72bfa4b583e7c09840d7b4e57a040fb6c7 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture3.jpg differ diff --git a/entry/src/main/resources/base/media/ic_picture4.jpg b/entry/src/main/resources/base/media/ic_picture4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..cbd43c1bbe966a82a3504fc8571538cbe2d23d7a Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture4.jpg differ diff --git a/entry/src/main/resources/base/media/ic_picture5.jpg b/entry/src/main/resources/base/media/ic_picture5.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c147d1cf3b3a9393d8e836f4ca55c9e0a6f4d1b6 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture5.jpg differ diff --git a/entry/src/main/resources/base/media/ic_picture6.jpg b/entry/src/main/resources/base/media/ic_picture6.jpg new file mode 100644 index 0000000000000000000000000000000000000000..94a482fa8cc7593bf963dc353599499d0e116144 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture6.jpg differ diff --git a/entry/src/main/resources/base/media/ic_picture7.jpg b/entry/src/main/resources/base/media/ic_picture7.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a365625b17643da362367d04f73c0a77ec2efbd1 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture7.jpg differ diff --git a/entry/src/main/resources/base/media/ic_picture8.jpg b/entry/src/main/resources/base/media/ic_picture8.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ffc9172ba5bbdf91620324d1d14bdf3934151f95 Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture8.jpg differ diff --git a/entry/src/main/resources/base/media/ic_picture9.jpg b/entry/src/main/resources/base/media/ic_picture9.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c2d2d72c5fe0f8c586624d5fca73e270362adf8e Binary files /dev/null and b/entry/src/main/resources/base/media/ic_picture9.jpg differ diff --git a/entry/src/main/resources/base/media/ic_public_favor.svg b/entry/src/main/resources/base/media/ic_public_favor.svg deleted file mode 100644 index fbb98de4bbb1f2e1f9e5f7d2adeeed8dd0f8b1fb..0000000000000000000000000000000000000000 --- a/entry/src/main/resources/base/media/ic_public_favor.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - Public/ic_public_favor_filled - - - - - - - - - - \ No newline at end of file diff --git a/entry/src/main/resources/base/media/ic_public_favor_filled.png b/entry/src/main/resources/base/media/ic_public_favor_filled.png deleted file mode 100644 index 75a8d7f242d72793a2a748d8d4d707a737b9c10c..0000000000000000000000000000000000000000 Binary files a/entry/src/main/resources/base/media/ic_public_favor_filled.png and /dev/null differ diff --git a/entry/src/main/resources/base/media/ic_social_circle1.png b/entry/src/main/resources/base/media/ic_social_circle1.png deleted file mode 100644 index c154bf4ce1ede2b1ab76d94a388748add9621005..0000000000000000000000000000000000000000 Binary files a/entry/src/main/resources/base/media/ic_social_circle1.png and /dev/null differ diff --git a/entry/src/main/resources/base/media/ic_social_circle2.jpg b/entry/src/main/resources/base/media/ic_social_circle2.jpg deleted file mode 100644 index 1f48c2abb9c15499951edb75092ec61bd92042a7..0000000000000000000000000000000000000000 Binary files a/entry/src/main/resources/base/media/ic_social_circle2.jpg and /dev/null differ diff --git a/entry/src/main/resources/base/media/ic_social_circle3.jpg b/entry/src/main/resources/base/media/ic_social_circle3.jpg deleted file mode 100644 index c743fffbde638107707801fb7740c530c4f6cdd2..0000000000000000000000000000000000000000 Binary files a/entry/src/main/resources/base/media/ic_social_circle3.jpg and /dev/null differ diff --git a/entry/src/main/resources/base/profile/form_config.json b/entry/src/main/resources/base/profile/form_config.json index 4bff58037e40c4044603d498306ae596d580e887..d20eb4b97bc3288ef13bb87eaacefe758c3e5b73 100644 --- a/entry/src/main/resources/base/profile/form_config.json +++ b/entry/src/main/resources/base/profile/form_config.json @@ -25,7 +25,7 @@ "name": "card_info_update", "displayName": "$string:widget1_display_name", "description": "$string:widget1_desc", - "src": "./ets/widgetupdate/pages/WidgetCardUpdate.ets", + "src": "./ets/widget/pages/WidgetCardUpdate.ets", "uiSyntax": "arkts", "window": { "designWidth": 720, @@ -36,7 +36,6 @@ "isDefault": false, "updateEnabled": true, "updateDuration": 1, - "scheduledUpdateTime": "10:30", "defaultDimension": "2*4", "supportDimensions": [ "2*4" diff --git a/entry/src/main/resources/en_US/element/string.json b/entry/src/main/resources/en_US/element/string.json index 7f6920cc7b0489edc1ec70d16d393023331e85b2..e1503af10a546e51a2413abd64247511ba6ca5c5 100644 --- a/entry/src/main/resources/en_US/element/string.json +++ b/entry/src/main/resources/en_US/element/string.json @@ -22,11 +22,11 @@ }, { "name": "widget_desc", - "value": "This is a service widget." + "value": "Example of recommended content list." }, { "name": "widget_display_name", - "value": "widget" + "value": "Card Example One" }, { "name": "card_list_title", @@ -150,11 +150,11 @@ }, { "name": "widget1_desc", - "value": "This is a service widget." + "value": "Recommended content examples." }, { "name": "widget1_display_name", - "value": "widget1" + "value": "Card Example Two" } ] } \ No newline at end of file diff --git a/entry/src/main/resources/zh_CN/element/string.json b/entry/src/main/resources/zh_CN/element/string.json index 2d246ccee24838fd4b72114826e2121e7eb049e9..7ef474c525980479daa039ced3d712151511f47a 100644 --- a/entry/src/main/resources/zh_CN/element/string.json +++ b/entry/src/main/resources/zh_CN/element/string.json @@ -22,11 +22,11 @@ }, { "name": "widget_desc", - "value": "This is a service widget." + "value": "推荐内容列表示例" }, { "name": "widget_display_name", - "value": "widget" + "value": "卡片示例一" }, { "name": "card_list_title", @@ -150,11 +150,11 @@ }, { "name": "widget1_desc", - "value": "This is a service widget." + "value": "推荐内容示例" }, { "name": "widget1_display_name", - "value": "widget1" + "value": "卡片示例二" } ] } \ No newline at end of file diff --git a/oh-package.json5 b/oh-package.json5 index ebdda7e54d1c41e952f1c7f6993c6d15ea3d146d..8bf916d4a165e0466c65bc49f58ab2e3c27e8931 100644 --- a/oh-package.json5 +++ b/oh-package.json5 @@ -4,7 +4,5 @@ "dependencies": { }, "devDependencies": { - "@ohos/hypium": "1.0.18", - "@ohos/hamock": "1.0.0" } } diff --git a/screenshots/device/form_second.en.png b/screenshots/device/form_second.en.png index 8b83900b469cdb7ad819f33503179f67cdfd83ec..0b9ed6eef873332cde951dbd7464640c38ecc7d1 100644 Binary files a/screenshots/device/form_second.en.png and b/screenshots/device/form_second.en.png differ diff --git a/screenshots/device/form_second.png b/screenshots/device/form_second.png index 141f9d029eeab50d56b57f077762d301e18ff2af..3a2892825f9c639cdbff57622d8445ad0056ce72 100644 Binary files a/screenshots/device/form_second.png and b/screenshots/device/form_second.png differ