diff --git a/AdaptiveCapabilities/build-profile.json5 b/AdaptiveCapabilities/build-profile.json5 index 81e3ebfbc3612eafa6d63357beed1ad2068b5bef..b2413df1922603b33350c28564d7a79b22dbc732 100644 --- a/AdaptiveCapabilities/build-profile.json5 +++ b/AdaptiveCapabilities/build-profile.json5 @@ -15,16 +15,29 @@ { "app": { + "signingConfigs": [], "products": [ { "name": "default", "signingConfig": "default", - "compileSdkVersion": 12, - "compatibleSdkVersion": 12, - "runtimeOS": "OpenHarmony" + "compatibleSdkVersion": "5.0.3(15)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } } ], - "signingConfigs": [] + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] }, "modules": [ { @@ -40,4 +53,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/MainAbility/MainAbility.ts b/AdaptiveCapabilities/entry/src/main/ets/MainAbility/MainAbility.ets similarity index 64% rename from AdaptiveCapabilities/entry/src/main/ets/MainAbility/MainAbility.ts rename to AdaptiveCapabilities/entry/src/main/ets/MainAbility/MainAbility.ets index 9125767a739ffca4f9a8fbdb02088d115d494779..a7ba6d41eee2518dea216964ce0343d49c3a905a 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/MainAbility/MainAbility.ts +++ b/AdaptiveCapabilities/entry/src/main/ets/MainAbility/MainAbility.ets @@ -13,41 +13,47 @@ * limitations under the License. */ -import UIAbility from '@ohos.app.ability.UIAbility' -import Logger from '../model/Logger' -import window from '@ohos.window' +import { UIAbility } from '@kit.AbilityKit'; +import { window } from '@kit.ArkUI'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import Logger from '../model/Logger'; export default class MainAbility extends UIAbility { - onCreate(want, launchParam) { - Logger.info('[Sample_AdaptiveCapabilities]', 'MainAbility onCreate') + onCreate() { + Logger.info('[Sample_AdaptiveCapabilities]', 'MainAbility onCreate'); } onDestroy() { - Logger.info('[Sample_AdaptiveCapabilities]', 'MainAbility onDestroy') + Logger.info('[Sample_AdaptiveCapabilities]', 'MainAbility onDestroy'); } - onWindowStageCreate(windowStage) { + onWindowStageCreate(windowStage: window.WindowStage) { // Main window is created, set main page for this ability - Logger.info('[Sample_AdaptiveCapabilities]', 'onWindowStageCreate') - windowStage.setUIContent(this.context, "pages/Index", null) - window.getTopWindow(this.context) - .then(windowObj => { - AppStorage.SetOrCreate('windowObj', windowObj) - }) + Logger.info('[Sample_AdaptiveCapabilities]', 'onWindowStageCreate'); + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + let windowObj = windowStage.getMainWindowSync(); + AppStorage.setOrCreate('windowObj', windowObj); + AppStorage.setOrCreate('uiContext', windowObj.getUIContext()); + }); } onWindowStageDestroy() { // Main window is destroyed, release UI related resources - Logger.info('[Sample_AdaptiveCapabilities]', 'onWindowStageDestroy') + Logger.info('[Sample_AdaptiveCapabilities]', 'onWindowStageDestroy'); } onForeground() { // Ability has brought to foreground - Logger.info('[Sample_AdaptiveCapabilities]', 'onForeground') + Logger.info('[Sample_AdaptiveCapabilities]', 'onForeground'); } onBackground() { // Ability has back to background - Logger.info('[Sample_AdaptiveCapabilities]', 'onBackground') + Logger.info('[Sample_AdaptiveCapabilities]', 'onBackground'); } -} +} \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/common/BreakpointSystem.ets b/AdaptiveCapabilities/entry/src/main/ets/common/BreakpointSystem.ets index ca6f6830bc36fb7773a80ac4f785c7941bb0e1a3..0b1a124fe294786007dd0fc335afea6d1d5cb379 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/common/BreakpointSystem.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/common/BreakpointSystem.ets @@ -13,129 +13,98 @@ * limitations under the License. */ -// [Start Breakpoint] -// common/breakpointsystem.ets import { mediaquery } from '@kit.ArkUI'; -export type BreakpointType = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; +export class BreakPointTypeOptionEntity implements BreakPointTypeOption { + xs?: T; + sm?: T; + md?: T; + lg?: T; + xl?: T; + xxl?: T; +} -export interface Breakpoint { - name: BreakpointType; - size: number; - mediaQueryListener?: mediaquery.MediaQueryListener; +declare interface BreakPointTypeOption { + xs?: T; + sm?: T; + md?: T; + lg?: T; + xl?: T; + xxl?: T; } +export class BreakPointType { + options: BreakPointTypeOption; + + constructor(option: BreakPointTypeOption) { + this.options = option; + } + + getValue(currentBreakPoint: string): T { + if (currentBreakPoint === 'xs') { + return this.options.xs as T; + } else if (currentBreakPoint === 'sm') { + return this.options.sm as T; + } else if (currentBreakPoint === 'md') { + return this.options.md as T; + } else if (currentBreakPoint === 'lg') { + return this.options.lg as T; + } else if (currentBreakPoint === 'xl') { + return this.options.xl as T; + } else if (currentBreakPoint === 'xxl') { + return this.options.xxl as T; + } else { + return this.options.xs as T; + } + } +} + +class BreakpointEntity { + name: string = ''; + size: number = 0; + mediaQueryListener?: mediaquery.MediaQueryListener; +} export class BreakpointSystem { - private static instance: BreakpointSystem; - private readonly breakpoints: Breakpoint[] = [ + private currentBreakpoint: string = 'md'; + private breakpoints: BreakpointEntity[] = [ { name: 'xs', size: 0 }, { name: 'sm', size: 320 }, { name: 'md', size: 600 }, { name: 'lg', size: 840 } ] - private states: Set>; - private constructor() { - this.states = new Set(); - } - - - public static getInstance(): BreakpointSystem { - if (!BreakpointSystem.instance) { - BreakpointSystem.instance = new BreakpointSystem(); + private updateCurrentBreakpoint(breakpoint: string) { + if (this.currentBreakpoint !== breakpoint) { + this.currentBreakpoint = breakpoint; + AppStorage.setOrCreate('currentBreakpoint', this.currentBreakpoint); + console.log('on current breakpoint: ' + this.currentBreakpoint); } - return BreakpointSystem.instance; - } - - - public attach(state: BreakpointState): void { - this.states.add(state); - } - - - public detach(state: BreakpointState): void { - this.states.delete(state); } - - public start() { - this.breakpoints.forEach((breakpoint: Breakpoint, index) => { - let condition: string; + public register() { + this.breakpoints.forEach((breakpoint: BreakpointEntity, index) => { + let condition: string = ''; if (index === this.breakpoints.length - 1) { - condition = `(${breakpoint.size}vp<=width)`; + condition = '(' + breakpoint.size + 'vp<=width' + ')'; } else { - condition = `(${breakpoint.size}vp<=width<${this.breakpoints[index + 1].size}vp)`; - } - breakpoint.mediaQueryListener = mediaquery.matchMediaSync(condition); - if (breakpoint.mediaQueryListener.matches) { - this.updateAllState(breakpoint.name); + condition = '(' + breakpoint.size + 'vp<=width<' + this.breakpoints[index + 1].size + 'vp)'; } + let uiContext = AppStorage.get('uiContext') as UIContext; + breakpoint.mediaQueryListener = uiContext.getMediaQuery().matchMediaSync(condition); breakpoint.mediaQueryListener.on('change', (mediaQueryResult) => { if (mediaQueryResult.matches) { - this.updateAllState(breakpoint.name); + this.updateCurrentBreakpoint(breakpoint.name); } }) }) } - - private updateAllState(type: BreakpointType): void { - this.states.forEach(state => state.update(type)); - } - - - public stop() { - this.breakpoints.forEach((breakpoint: Breakpoint, index) => { - if (breakpoint.mediaQueryListener) { + public unregister() { + this.breakpoints.forEach((breakpoint: BreakpointEntity) => { + if (breakpoint != undefined && breakpoint.mediaQueryListener != undefined) { breakpoint.mediaQueryListener.off('change'); } }) - this.states.clear(); } -} - - -export interface BreakpointOptions { - xs?: T; - sm?: T; - md?: T; - lg?: T; - xl?: T; - xxl?: T; -} - - -export class BreakpointState { - public value: T | undefined = undefined; - private options: BreakpointOptions; - - constructor(options: BreakpointOptions) { - this.options = options; - } - - - static of(options: BreakpointOptions): BreakpointState { - return new BreakpointState(options); - } - - - public update(type: BreakpointType): void { - if (type === 'xs') { - this.value = this.options.xs; - } else if (type === 'sm') { - this.value = this.options.sm; - } else if (type === 'md') { - this.value = this.options.md; - } else if (type === 'lg') { - this.value = this.options.lg; - } else if (type === 'xl') { - this.value = this.options.xl; - } else if (type === 'xxl') { - this.value = this.options.xxl; - } else { - this.value = undefined; - } - } -} -// [End Breakpoint] \ No newline at end of file +} \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/common/ColorEntity.ets b/AdaptiveCapabilities/entry/src/main/ets/common/ColorEntity.ets index 1003757c682bbc8c56493d95b27a16764ca0a3fc..78ede9b62d0f40b534e8a4cacc2ca2dfd51c73e7 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/common/ColorEntity.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/common/ColorEntity.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -export class ColorArr{ - index:number=0; - color:Resource|Color=0; +export class ColorArr { + index: number = 0; + color: Resource | Color = 0; } \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/common/DirectoryList.ets b/AdaptiveCapabilities/entry/src/main/ets/common/DirectoryList.ets index 507ee3a14f425f51839a18727d58c1a82ff59a7f..bd9d61d33725e0451e4e7b01f44b485a7d65969a 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/common/DirectoryList.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/common/DirectoryList.ets @@ -13,8 +13,6 @@ * limitations under the License. */ -import router from '@ohos.router' - class DirectoryItem { title: Resource | string = ''; uri: string = ''; @@ -23,8 +21,8 @@ class DirectoryItem { @Component struct DirectoryList { - private directory: DirectoryItem[]=[]; - private title?: Resource; + directory: DirectoryItem[] = []; + title?: Resource; build() { Scroll() { @@ -34,24 +32,24 @@ struct DirectoryList { .fontWeight(FontWeight.Bold) .height(100); - ForEach(this.directory, (item : DirectoryItem) => { + ForEach(this.directory, (item: DirectoryItem) => { Button(item.title) - .id(item.id) - .fontSize(20) - .width('90%') - .height(55) - .margin(12) - .backgroundColor('#007DFF') - .onClick(() => { - router.pushUrl({ - url: item.uri - }) - }); - },(item:DirectoryItem)=>JSON.stringify(item)); + .id(item.id) + .fontSize(20) + .width('90%') + .height(55) + .margin(12) + .backgroundColor('#007DFF') + .onClick(() => { + this.getUIContext().getRouter().pushUrl({ + url: item.uri + }) + }); + }, (item: DirectoryItem) => JSON.stringify(item)); } } .width('100%') - .padding({left: 10, right: 10, bottom: 100}); + .padding({ left: 10, right: 10, bottom: 100 }); } } diff --git a/AdaptiveCapabilities/entry/src/main/ets/common/GetValueOnBreakpoint.ets b/AdaptiveCapabilities/entry/src/main/ets/common/GetValueOnBreakpoint.ets index f210a9c1cf02d38326b19cfa30c29e41fc057fd5..d34e301b75f3b462401f07cff8a538c6b5cbd50a 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/common/GetValueOnBreakpoint.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/common/GetValueOnBreakpoint.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -import window from '@ohos.window'; +import { window } from '@kit.ArkUI'; export class Breakpoints { xs: number = 0; @@ -27,11 +27,12 @@ export default function getValueOnBreakpoint(breakpointsLabels: string[], breakp if (breakpointsLabels.length < 4) { return ''; } - let windowObj: window.Window |undefined= AppStorage.Get('windowObj'); - if(windowObj == undefined){ + let windowObj: window.Window | undefined = AppStorage.get('windowObj'); + if (windowObj == undefined) { return ''; } - let windowWidthVp = px2vp(windowObj.getWindowProperties().windowRect.width); + let uiContext = AppStorage.get('uiContext') as UIContext; + let windowWidthVp = uiContext.px2vp(windowObj.getWindowProperties().windowRect.width); let newBreakpoint: string = ''; if (windowWidthVp < breakpoints.sm) { newBreakpoint = breakpointsLabels[0]; diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/equipartitionCapability/EquipartitionCapability.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/equipartitionCapability/EquipartitionCapability.ets index e1ff4afcb0fc1867a51bf791eccbd89c64e71c39..76b569138e8b0743dddcaa29bc1b5462a7e638de 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/equipartitionCapability/EquipartitionCapability.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/equipartitionCapability/EquipartitionCapability.ets @@ -13,24 +13,28 @@ * limitations under the License. */ +// Start EquipartitionCapability @Entry @Component struct EquipartitionCapability { - private list: number [] = [0, 1, 2, 3] - @State rate: number = 0.6 + @State rate: number = 0.6; + private list: number [] = [0, 1, 2, 3]; - @Builder slider() { + // Bottom slider - adjust container dimensions via slider drag interaction. + @Builder + slider() { Slider({ value: this.rate * 100, min: 30, max: 60 }) .blockColor(Color.White) .width('60%') .height(50) .onChange((value: number) => { - this.rate = value / 100 + this.rate = value / 100; }) .position({ x: '20%', y: '80%' }) } - @Builder Item() { + @Builder + Item() { Column() { Image($r('app.media.icon')) .width(48) @@ -44,22 +48,26 @@ struct EquipartitionCapability { .textAlign(TextAlign.Center) .margin({ top: 8 }) .padding({ bottom: 15 }) - }.width(80).height(102) + } + .width(80) + .height(102) } build() { Row() { Column() { + // Distribute remaining space evenly along the main axis of the parent container. Flex({ justifyContent: FlexAlign.SpaceEvenly }) { - ForEach(this.list, () => { - this.Item() - }) + ForEach(this.list, (item: number) => { + this.Item(); + }, (item: number, index: number) => JSON.stringify(item) + index) } + // Distribute remaining space evenly along the main axis of the parent container. Flex({ justifyContent: FlexAlign.SpaceEvenly }) { - ForEach(this.list, () => { - this.Item() - }) + ForEach(this.list, (item: number) => { + this.Item(); + }, (item: number, index: number) => JSON.stringify(item) + index) } } .width(this.rate * 100 + '%') @@ -76,4 +84,5 @@ struct EquipartitionCapability { .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Center) } -} \ No newline at end of file +} +// End EquipartitionCapability \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/extensionCapability/ExtensionCapability1.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/extensionCapability/ExtensionCapability1.ets index 5c504696a764cf9cd0b5ea555d2d2e4be3e84ace..fd77a67e47bb7e5012bd725756908693d6ca1d40 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/extensionCapability/ExtensionCapability1.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/extensionCapability/ExtensionCapability1.ets @@ -13,29 +13,31 @@ * limitations under the License. */ +// Start ExtensionCapability1 @Entry @Component struct ExtensionCapability1 { - @State rate: number = 0.60 - private appList: number [] = [0, 1, 2, 3, 4, 5, 6, 7] + @State rate: number = 0.60; + private appList: number [] = [0, 1, 2, 3, 4, 5, 6, 7]; - @Builder slider() { + @Builder + slider() { Slider({ value: this.rate * 100, min: 8, max: 60 }) .blockColor(Color.White) .width('60%') .height(50) .onChange((value: number) => { - this.rate = value / 100 + this.rate = value / 100; }) .position({ x: '20%', y: '80%' }) } build() { Row() { - // implement extension capability through Scroll and Row(or Column) Components. + // Implement extension capability through Scroll and Row(or Column) components. Scroll() { Row({ space: 10 }) { - ForEach(this.appList, () => { + ForEach(this.appList, (item: number, index: number) => { Column() { Image($r('app.media.icon')) .width(48) @@ -49,8 +51,10 @@ struct ExtensionCapability1 { .textAlign(TextAlign.Center) .margin({ top: 8 }) .padding({ bottom: 15 }) - }.width(80).height(102) - }) + } + .width(80) + .height(102) + }, (item: number, index: number) => JSON.stringify(item) + index) } .padding({ top: 16, left: 10 }) .height(118) @@ -67,4 +71,6 @@ struct ExtensionCapability1 { .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Center) } -} \ No newline at end of file +} + +// End ExtensionCapability1 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/extensionCapability/ExtensionCapability2.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/extensionCapability/ExtensionCapability2.ets index 60ef1babcf832255b9b8e1e157285dd8b3a4684d..20bc40bc689c5980d7ba38650c2f4cf9883b9243 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/extensionCapability/ExtensionCapability2.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/extensionCapability/ExtensionCapability2.ets @@ -13,19 +13,21 @@ * limitations under the License. */ +// Start ExtensionCapability2 @Entry @Component struct ExtensionCapability2 { - @State rate: number = 0.60 - private appList: number [] = [0, 1, 2, 3, 4, 5, 6, 7] + @State rate: number = 0.60; + private appList: number [] = [0, 1, 2, 3, 4, 5, 6, 7]; - @Builder slider() { + @Builder + slider() { Slider({ value: this.rate * 100, min: 8, max: 60 }) .blockColor(Color.White) .width('60%') .height(50) .onChange((value: number) => { - this.rate = value / 100 + this.rate = value / 100; }) .position({ x: '20%', y: '80%' }) } @@ -33,9 +35,9 @@ struct ExtensionCapability2 { build() { Row() { Row({ space: 10 }) { - // implement extension capability through List component. + // Implement extension capability through List component. List({ space: 10 }) { - ForEach(this.appList, () => { + ForEach(this.appList, (item: number, index: number) => { ListItem() { Column() { Image($r('app.media.icon')) @@ -50,9 +52,13 @@ struct ExtensionCapability2 { .textAlign(TextAlign.Center) .margin({ top: 8 }) .padding({ bottom: 15 }) - }.width(80).height(102) - }.width(80).height(102) - }) + } + .width(80) + .height(102) + } + .width(80) + .height(102) + }, (item: number, index: number) => JSON.stringify(item) + index) } .padding({ top: 16, left: 10 }) .listDirection(Axis.Horizontal) @@ -70,4 +76,6 @@ struct ExtensionCapability2 { .justifyContent(FlexAlign.Center) .alignItems(VerticalAlign.Center) } -} \ No newline at end of file +} + +// End ExtensionCapability2 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/flexibleCapability/FlexibleCapability1.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/flexibleCapability/FlexibleCapability1.ets index a5632f682406049ae3594e118f6e79a9e43e76fe..8eca326c3651c7500e11724e6fcc0abf5881eb42 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/flexibleCapability/FlexibleCapability1.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/flexibleCapability/FlexibleCapability1.ets @@ -13,17 +13,20 @@ * limitations under the License. */ +// Start FlexibleCapability1 @Entry @Component struct FlexibleCapability1 { - @State sliderWidth: number = 1000 + @State sliderWidth: number = 1000; - @Builder slider() { + // Bottom slider - adjust container size by dragging the slider. + @Builder + slider() { Slider({ value: this.sliderWidth, min: 300, max: 1000 }) .blockColor(Color.White) .width('60%') .onChange((value: number) => { - this.sliderWidth = value + this.sliderWidth = value; }) .position({ x: '20%', y: '80%' }) } @@ -31,6 +34,7 @@ struct FlexibleCapability1 { build() { Column() { Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { + // Distribute all extra space to the image using flexGrow and allocate all insufficient space to the side margins using flexShrink. Row() .width(150) .height(400) @@ -50,7 +54,8 @@ struct FlexibleCapability1 { .backgroundColor('#FFFFFF') .flexGrow(0) .flexShrink(1) - }.width(this.sliderWidth) + } + .width(this.sliderWidth) this.slider() } @@ -60,4 +65,6 @@ struct FlexibleCapability1 { .alignItems(HorizontalAlign.Center) .justifyContent(FlexAlign.Center) } -} \ No newline at end of file +} + +// End FlexibleCapability1 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/flexibleCapability/FlexibleCapability2.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/flexibleCapability/FlexibleCapability2.ets index e19630a43019ff867f8839a6382ab7c8faf21f56..91e12033b964998cce6be018f7a8bfaa0a3f94d5 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/flexibleCapability/FlexibleCapability2.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/flexibleCapability/FlexibleCapability2.ets @@ -13,17 +13,20 @@ * limitations under the License. */ +// Start FlexibleCapability2 @Entry @Component struct FlexibleCapability2 { - @State rate: number = 0.8 + @State rate: number = 0.8; - @Builder slider() { + // Bottom slider - resize container by dragging the slider control. + @Builder + slider() { Slider({ value: this.rate * 100, min: 55, max: 80 }) .blockColor(Color.White) .width('60%') .onChange((value: number) => { - this.rate = value / 100 + this.rate = value / 100; }) .position({ x: '20%', y: '80%' }) } @@ -37,6 +40,7 @@ struct FlexibleCapability2 { .height(22) .fontWeight(FontWeight.Medium) .lineHeight(22) + // Implement stretch capability using the Blank component. Blank() Toggle({ type: ToggleType.Switch }) .width(36) @@ -56,4 +60,5 @@ struct FlexibleCapability2 { .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Center) } -} \ No newline at end of file +} +// End FlexibleCapability2 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/hiddenCapability/HiddenCapability.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/hiddenCapability/HiddenCapability.ets index efcfb2193d135f0fc5a69bd4027d6d4b688cc2e1..37dd4f67c896e32e299ce2d3a52857f80e24ea83 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/hiddenCapability/HiddenCapability.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/hiddenCapability/HiddenCapability.ets @@ -13,59 +13,76 @@ * limitations under the License. */ +// Start HiddenCapability @Entry @Component struct HiddenCapability { - @State rate: number = 0.8 // slider宽度比例 + @State rate: number = 0.8; - @Builder slider() { + @Builder + slider() { Slider({ value: this.rate * 100, min: 10, max: 80 }) .blockColor(Color.White) .width('60%') .height(50) .onChange((value: number) => { - this.rate = value / 100 + this.rate = value / 100; }) .position({ x: '20%', y: '80%' }) } build() { - Row() { + Column() { Row() { - Image($r('app.media.favorite')) - .width(48) - .height(48) - .objectFit(ImageFit.Contain) - .margin({ left: 12, right: 12 }) - .displayPriority(1) + Row() { + Image($r('app.media.favorite')) + .width(48) + .height(48) + .objectFit(ImageFit.Contain) + } + // Layout priority. + .displayPriority(1) + .padding({ left: 12, right: 12 }) - Image($r('app.media.down')) - .width(48) - .height(48) - .objectFit(ImageFit.Contain) - .margin({ left: 12, right: 12 }) - .displayPriority(2) + Row() { + Image($r('app.media.down')) + .width(48) + .height(48) + .objectFit(ImageFit.Contain) + } + // Layout priority. + .displayPriority(2) + .padding({ left: 12, right: 12 }) - Image($r('app.media.pause')) - .width(48) - .height(48) - .objectFit(ImageFit.Contain) - .margin({ left: 12, right: 12 }) - .displayPriority(3) + Row() { + Image($r('app.media.pause')) + .width(48) + .height(48) + .objectFit(ImageFit.Contain) + } + // Layout priority. + .displayPriority(3) + .padding({ left: 12, right: 12 }) - Image($r('app.media.next')) - .width(48) - .height(48) - .objectFit(ImageFit.Contain) - .margin({ left: 12, right: 12 }) - .displayPriority(2) + Row() { + Image($r('app.media.next')) + .width(48) + .height(48) + .objectFit(ImageFit.Contain) + } + // Layout priority. + .displayPriority(2) + .padding({ left: 12, right: 12 }) - Image($r('app.media.list')) - .width(48) - .height(48) - .objectFit(ImageFit.Contain) - .margin({ left: 12, right: 12 }) - .displayPriority(1) + Row() { + Image($r('app.media.list')) + .width(48) + .height(48) + .objectFit(ImageFit.Contain) + } + // Layout priority. + .displayPriority(1) + .padding({ left: 12, right: 12 }) } .width(this.rate * 100 + '%') .height(96) @@ -78,7 +95,9 @@ struct HiddenCapability { .width('100%') .height('100%') .backgroundColor('#F1F3F5') - .alignItems(VerticalAlign.Center) + .alignItems(HorizontalAlign.Center) .justifyContent(FlexAlign.Center) } -} \ No newline at end of file +} + +// End HiddenCapability \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/proportionCapability/ProportionCapability.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/proportionCapability/ProportionCapability.ets index 6bf9a0d650fd934d8b8f34ece0c4fedd9946b8bd..ab138c64d16698e26eda7b823449a459c9c130d0 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/proportionCapability/ProportionCapability.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/proportionCapability/ProportionCapability.ets @@ -13,18 +13,21 @@ * limitations under the License. */ +// Start ProportionCapability @Entry @Component struct ProportionCapability { - @State rate: number = 0.5 + @State rate: number = 0.5; - @Builder slider() { + // Bottom slider - adjust container size through slider drag interaction. + @Builder + slider() { Slider({ value: 100, min: 25, max: 50 }) .blockColor(Color.White) .width('60%') .height(50) .onChange((value: number) => { - this.rate = value / 100 + this.rate = value / 100; }) .position({ x: '20%', y: '80%' }) } @@ -38,7 +41,8 @@ struct ProportionCapability { .height(48) } .height(96) - .width('33%') + // Set the layout weight of child components along the main axis of the parent container. + .layoutWeight(1) .justifyContent(FlexAlign.Center) Column() { @@ -47,7 +51,7 @@ struct ProportionCapability { .height(48) } .height(96) - .width('34%') + .layoutWeight(1) .backgroundColor('#66F1CCB8') .justifyContent(FlexAlign.Center) @@ -57,7 +61,7 @@ struct ProportionCapability { .height(48) } .height(96) - .width('33%') + .layoutWeight(1) .justifyContent(FlexAlign.Center) } .width(this.rate * 100 + '%') @@ -73,4 +77,5 @@ struct ProportionCapability { .alignItems(VerticalAlign.Center) .justifyContent(FlexAlign.Center) } -} \ No newline at end of file +} +// End ProportionCapability \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/scaleCapability/ScaleCapability.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/scaleCapability/ScaleCapability.ets index 280b9e75f79361de146a49188792fe4ab3f26c0c..7daf8b20807239111c9ff66f9cabbad21bfb1f68 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/scaleCapability/ScaleCapability.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/scaleCapability/ScaleCapability.ets @@ -13,27 +13,40 @@ * limitations under the License. */ +// Start ScaleCapability @Entry @Component struct ScaleCapability { - @State sliderWidth: number = 400 - @State sliderHeight: number = 400 + @State sliderWidth: number = 400; + @State sliderHeight: number = 400; - @Builder slider() { - Slider({ value: this.sliderWidth, min: 100, max: 400, style: SliderStyle.OutSet }) + // Bottom slider - adjust container size through slider drag interaction. + @Builder + slider() { + Slider({ + value: this.sliderWidth, + min: 100, + max: 400, + style: SliderStyle.OutSet + }) .blockColor(Color.White) .width('60%') .height(50) .onChange((value: number) => { - this.sliderWidth = value + this.sliderWidth = value; }) .position({ x: '20%', y: '80%' }) - Slider({ value: this.sliderHeight, min: 100, max: 400, style: SliderStyle.OutSet }) + Slider({ + value: this.sliderHeight, + min: 100, + max: 400, + style: SliderStyle.OutSet + }) .blockColor(Color.White) .width('60%') .height(50) .onChange((value: number) => { - this.sliderHeight = value + this.sliderHeight = value; }) .position({ x: '20%', y: '87%' }) } @@ -46,7 +59,9 @@ struct ScaleCapability { .width('100%') .height('100%') } + // Maintain fixed aspect ratio. .aspectRatio(1) + // Decorative border (purely for visual demonstration purposes). .border({ width: 2, color: '#66F1CCB8' }) } .backgroundColor('#FFFFFF') @@ -63,4 +78,6 @@ struct ScaleCapability { .alignItems(HorizontalAlign.Center) .justifyContent(FlexAlign.Center) } -} \ No newline at end of file +} + +// End ScaleCapability \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/wrapCapability/WrapCapability.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/wrapCapability/WrapCapability.ets index 37873e7e815cabdeb4964ef26db49cd8f41ca53d..38df031c5b821a8b7bd8ab93aea71e1f2f0b4c61 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/wrapCapability/WrapCapability.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/atomicLayoutCapability/wrapCapability/WrapCapability.ets @@ -13,43 +13,45 @@ * limitations under the License. */ +// Start WrapCapabilitySample @Entry @Component struct WrapCapabilitySample { - @State rate: number = 0.7 - private imageList: Resource [] = [ + @State rate: number = 0.7; + imageList: Resource [] = [ $r('app.media.flexWrap1'), $r('app.media.flexWrap2'), $r('app.media.flexWrap3'), $r('app.media.flexWrap4'), $r('app.media.flexWrap5'), $r('app.media.flexWrap6') - ] + ]; - @Builder slider() { + @Builder + slider() { Slider({ value: this.rate * 100, min: 50, max: 70 }) .blockColor(Color.White) .width('60%') .height(50) .onChange((value: number) => { - this.rate = value / 100 + this.rate = value / 100; }) .position({ x: '20%', y: '87%' }) } build() { - Row() { + Column() { Flex({ alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center, wrap: FlexWrap.Wrap }) { - ForEach(this.imageList, (item : Resource) => { + ForEach(this.imageList, (item: Resource, index: number) => { Image(item) - .width(72) + .width(192) .height(138) .padding(10) - }) + }, (item: Resource, index: number) => JSON.stringify(item) + index) } .backgroundColor('#FFFFFF') .padding(20) @@ -61,7 +63,9 @@ struct WrapCapabilitySample { .width('100%') .height('100%') .backgroundColor('#F1F3F5') - .alignItems(VerticalAlign.Center) + .alignItems(HorizontalAlign.Center) .justifyContent(FlexAlign.Center) } -} \ No newline at end of file +} + +// End WrapCapabilitySample \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample1.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample1.ets index 297f1ffe9ae30ceba25894b4e4257b4b0bd82f97..55b189ddcf0af6459eb422979e99519a34e38fb8 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample1.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample1.ets @@ -13,21 +13,15 @@ * limitations under the License. */ -// [Start GridRowSample1] +// Start GridRowSample1 @Entry +@Preview @Component struct GridRowSample1 { - @State private currentBreakpoint: string = 'unknown'; + @State currentBreakpoint: string = 'md'; build() { - // Adjust the breakpoint value ranges and enable more breakpoints. - // Note: The modified breakpoint values must include the 'vp' unit. - GridRow({ - breakpoints: { - value: ['600vp', '700vp', '800vp', '900vp', '1000vp'], - reference: BreakpointsReference.WindowSize - } - }) { + GridRow({ breakpoints: { value: ['600vp', '700vp', '800vp', '900vp', '1000vp'] } }) { GridCol({ span: { xs: 12, @@ -38,15 +32,20 @@ struct GridRowSample1 { xxl: 12 } }) { - Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Row() { Text(this.currentBreakpoint) - .fontSize(50) - .fontWeight(FontWeight.Medium) + .fontSize(100) + .fontWeight(FontWeight.Bolder) } + .width('100%') + .height('100%') + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Center) } - }.onBreakpointChange((currentBreakpoint: string) => { - this.currentBreakpoint = currentBreakpoint; + } + .onBreakpointChange((breakPoint: string) => { + this.currentBreakpoint = breakPoint; }) } } -// [End GridRowSample1] \ No newline at end of file +// End GridRowSample1 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample10.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample10.ets index 08526336718ffb2c65a06c9a1af555c52abf5f0c..7952a3ffc1e7cc9094a7a2055a62f75c156eb363 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample10.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample10.ets @@ -199,7 +199,7 @@ struct GridRowSample10 { } .width('100%') .height('30%') - .padding({ left: 10, right: 10 }); + .padding({left: 10, right: 10}); } .width('100%') .height('100%') @@ -222,6 +222,7 @@ enum VerDirection { const COL1_POSITIONS = [0, 2, 4]; // The values of the first component class GridColController { + moveAllInHor(pos: HorDirection, inst: GridRowSample10) { switch (pos) { case HorDirection.LEFT: diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample2.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample2.ets index cbee664d3b082493c0554ff4fc6caf4f598ae557..073594238094210f07d654a3d68832cdf9acafa7 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample2.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample2.ets @@ -13,11 +13,11 @@ * limitations under the License. */ -// [Start GridRowSample2] +// Start GridRowSample2 @Entry @Component struct GridRowSample2 { - @State private currentBreakpoint: string = 'unknown'; + @State currentBreakpoint: string = 'md'; build() { // Users can adjust the width of the sidebar and content area by dragging the divider in the sidebar component. @@ -28,7 +28,6 @@ struct GridRowSample2 { .width('100%') .backgroundColor('#19000000') - // Content area, resizable range: [550vp, 50vp]. GridRow({ breakpoints: { @@ -46,25 +45,30 @@ struct GridRowSample2 { xxl: 12 } }) { - Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { + Row() { Text(this.currentBreakpoint) .fontSize(50) - .fontWeight(FontWeight.Medium) + .fontWeight(FontWeight.Bolder) } + .width('100%') + .height('100%') + .justifyContent(FlexAlign.Center) + .alignItems(VerticalAlign.Center) } } .onBreakpointChange((currentBreakpoint: string) => { - this.currentBreakpoint = currentBreakpoint; + this.currentBreakpoint = currentBreakpoint }) .width('100%') } // The sidebar does not auto-hide when dragged to its minimum width. .autoHide(false) .sideBarWidth(100) - // Minimum width of the sidebar + // Minimum width of the sidebar. .minSideBarWidth(100) - // Maximum width of the sidebar + // Maximum width of the sidebar. .maxSideBarWidth(600) } } -// [End GridRowSample2] \ No newline at end of file + +// End GridRowSample2 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample3.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample3.ets index c03748b259aa5a71f692c30da06e1185c6ba1fe3..fc1aec36221dae1fcc7895f00848d246d3ea2bd7 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample3.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample3.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -// [Start GridRowSample3] +// Start GridRowSample3 @Entry @Component struct GridRowSample3 { @@ -27,7 +27,7 @@ struct GridRowSample3 { ]; build() { - // Configure the values of columns and gutter at different breakpoints + // Config the values of columns and gutter at different breakpoints. GridRow({ columns: { sm: 4, md: 8, lg: 12 }, gutter: { x: { sm: 8, md: 16, lg: 24 }, y: { sm: 8, md: 16, lg: 24 } } @@ -35,12 +35,12 @@ struct GridRowSample3 { ForEach(this.bgColors, (bgColor: ResourceColor) => { GridCol({ span: { sm: 2, md: 2, lg: 2 } }) { Row() + .width('100%') .backgroundColor(bgColor) .height(30) - .width('100%') } }) } } } -// [End GridRowSample3] \ No newline at end of file +// End GridRowSample3 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample4.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample4.ets index 4bddd504afadb046c77610f1b3db4e1b349bd0a5..d9c2b552d1dbc21442f8efdb3883b9876e0478c2 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample4.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample4.ets @@ -13,11 +13,11 @@ * limitations under the License. */ -// [Start GridRowSample4] +// Start GridRowSample4 @Entry @Component struct GridRowSample4 { - @State private gridMargin: number = 0; + @State gridMargin: number = 0; build() { Column() { @@ -25,23 +25,19 @@ struct GridRowSample4 { .width('100%') .height(30) - // Control the left and right spacing of the grid using padding + // Control the left and right spacing of the grid using padding. GridRow() { - GridCol({ - span: { - xs: 12, - sm: 12, - md: 12, - lg: 12 - } - }) { - Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { - Text("padding") + GridCol({ span: { sm: 12, md: 12, lg: 12 } }) { + Row() { + Text('padding') .fontSize(24) .fontWeight(FontWeight.Medium) } - .backgroundColor('#19000000') .width('100%') + .height('100%') + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Center) + .backgroundColor('#19000000') } } .height(50) @@ -57,25 +53,23 @@ struct GridRowSample4 { } }) - Row().width('100%').height(30) + Row() + .width('100%') + .height(30) - // Control the left and right spacing of the grid using margin + // Control the left and right spacing of the grid using margin. GridRow() { - GridCol({ - span: { - xs: 12, - sm: 12, - md: 12, - lg: 12 - } - }) { - Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { - Text("margin") + GridCol({ span: { sm: 12, md: 12, lg: 12 } }) { + Row() { + Text('margin') .fontSize(24) .fontWeight(FontWeight.Medium) } - .backgroundColor('#19000000') .width('100%') + .height('100%') + .alignItems(VerticalAlign.Center) + .justifyContent(FlexAlign.Center) + .backgroundColor('#19000000') } } .height(50) @@ -85,4 +79,4 @@ struct GridRowSample4 { } } } -// [End GridRowSample4] \ No newline at end of file +// End GridRowSample4 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample5.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample5.ets index 00bd594ef8e0614b23eef770b4aaca31b15e8a9b..8f95e81cf5cffdc1a02287b0171ec1483dee4f8f 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample5.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample5.ets @@ -13,39 +13,34 @@ * limitations under the License. */ -// [Start GridRowSample5] -class Obj { - public index: number = 1; - public color: Resource = $r('sys.color.ohos_id_color_palette_aux1'); -} +import { ColorArr } from '../../../common/ColorEntity'; +// Start GridRowSample5 @Entry @Component struct GridRowSample5 { - private elements: Obj[] = [ + private elements: ColorArr[] = [ { index: 1, color: $r('sys.color.ohos_id_color_palette_aux1') }, { index: 2, color: $r('sys.color.ohos_id_color_palette_aux2') }, { index: 3, color: $r('sys.color.ohos_id_color_palette_aux3') }, { index: 4, color: $r('sys.color.ohos_id_color_palette_aux4') }, { index: 5, color: $r('sys.color.ohos_id_color_palette_aux5') }, - { index: 6, color: $r('sys.color.ohos_id_color_palette_aux6') }, + { index: 6, color: $r('sys.color.ohos_id_color_palette_aux6') } ]; build() { GridRow() { - ForEach(this.elements, (item: Obj) => { - GridCol({ span: { sm: 6, md: (item.index % 3 === 0) ? 0 : 4, lg: 3 } }) { + ForEach(this.elements, (item: ColorArr) => { + GridCol({ span: { sm: 6, md: item.index % 3 === 0 ? 0 : 4, lg: 3 } }) { Row() { - Text('' + item.index) - .fontSize(24) + Text(`${item.index}`).fontSize(24) } .justifyContent(FlexAlign.Center) .backgroundColor(item.color) .height(30) - .width('100%') } - }) + }, (item: ColorArr, index: number) => JSON.stringify(item) + index) } } } -// [End GridRowSample5] \ No newline at end of file +// End GridRowSample5 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample6.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample6.ets index 7c9868e92a1f7bffc505db821028a508d058089d..d26a602b446219d7608792784ea4a4ed295d3ff9 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample6.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample6.ets @@ -13,39 +13,38 @@ * limitations under the License. */ -// [Start GridRowSample6] -class Obj { - public index: number = 1; - public color: Resource = $r('sys.color.ohos_id_color_palette_aux1'); -} +import { ColorArr } from '../../../common/ColorEntity'; +// Start GridRowSample6 @Entry @Component struct GridRowSample6 { - private elements: Obj[] = [ + private elements: ColorArr[] = [ { index: 1, color: $r('sys.color.ohos_id_color_palette_aux1') }, { index: 2, color: $r('sys.color.ohos_id_color_palette_aux2') }, { index: 3, color: $r('sys.color.ohos_id_color_palette_aux3') }, { index: 4, color: $r('sys.color.ohos_id_color_palette_aux4') }, { index: 5, color: $r('sys.color.ohos_id_color_palette_aux5') }, - { index: 6, color: $r('sys.color.ohos_id_color_palette_aux6') }, + { index: 6, color: $r('sys.color.ohos_id_color_palette_aux6') } ]; build() { GridRow() { - ForEach(this.elements, (item: Obj) => { - GridCol({ span: { sm: 6, md: 4, lg: 3 }, offset: { sm: 0, md: 2, lg: 1 } }) { + ForEach(this.elements, (item: ColorArr) => { + GridCol({ + span: { sm: 6, md: 4, lg: 3 }, + offset: { sm: 0, md: 2, lg: 1 } + }) { Row() { - Text('' + item.index) + Text(`${item.index}`) .fontSize(24) } .justifyContent(FlexAlign.Center) .backgroundColor(item.color) .height(30) - .width('100%') } - }) + }, (item: ColorArr, index: number) => JSON.stringify(item) + index) } } } -// [End GridRowSample6] \ No newline at end of file +// End GridRowSample6 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample7.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample7.ets index 22d61c679b9fbcd6a19988dbe6a02fe4f6619c7a..afc7d8c5b6efb47eeb55b8246f8f4c4ef60a5d23 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample7.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample7.ets @@ -13,39 +13,38 @@ * limitations under the License. */ -// [Start GridRowSample7] -class Obj { - public index: number = 1; - public color: Resource = $r('sys.color.ohos_id_color_palette_aux1'); -} +import { ColorArr } from '../../../common/ColorEntity'; +// Start GridRowSample7 @Entry @Component struct GridRowSample7 { - private elements: Obj[] = [ + private elements: ColorArr[] = [ { index: 1, color: $r('sys.color.ohos_id_color_palette_aux1') }, { index: 2, color: $r('sys.color.ohos_id_color_palette_aux2') }, { index: 3, color: $r('sys.color.ohos_id_color_palette_aux3') }, { index: 4, color: $r('sys.color.ohos_id_color_palette_aux4') }, { index: 5, color: $r('sys.color.ohos_id_color_palette_aux5') }, - { index: 6, color: $r('sys.color.ohos_id_color_palette_aux6') }, + { index: 6, color: $r('sys.color.ohos_id_color_palette_aux6') } ]; build() { GridRow() { - ForEach(this.elements, (item: Obj) => { - GridCol({ span: { sm: 6, md: 4, lg: 3 }, order: { lg: (6 - item.index) } }) { + ForEach(this.elements, (item: ColorArr) => { + GridCol({ + span: { sm: 6, md: 4, lg: 3 }, + order: { lg: (6 - item.index) } + }) { Row() { - Text('' + item.index) + Text(`${item.index}`) .fontSize(24) } .justifyContent(FlexAlign.Center) .backgroundColor(item.color) .height(30) - .width('100%') } - }) + }, (item: ColorArr, index: number) => JSON.stringify(item) + index) } } } -// [End GridRowSample7] \ No newline at end of file +// End GridRowSample7 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample8.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample8.ets index 8ba45d09aaff6df692bd1e0ee75d94e45865b45b..3012c73eff00823514d2ba9a9e3e973d7f4ef1fd 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample8.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample8.ets @@ -13,44 +13,40 @@ * limitations under the License. */ -// [Start GridRowSample8] -class Obj { - public index: number = 1; - public color: Resource = $r('sys.color.ohos_id_color_palette_aux1'); -} +import { ColorArr } from '../../../common/ColorEntity'; +// Start GridRowSample8 @Entry @Component struct GridRowSample8 { - private elements: Obj[] = [ + private elements: ColorArr[] = [ { index: 1, color: $r('sys.color.ohos_id_color_palette_aux1') }, { index: 2, color: $r('sys.color.ohos_id_color_palette_aux2') }, { index: 3, color: $r('sys.color.ohos_id_color_palette_aux3') }, { index: 4, color: $r('sys.color.ohos_id_color_palette_aux4') }, { index: 5, color: $r('sys.color.ohos_id_color_palette_aux5') }, - { index: 6, color: $r('sys.color.ohos_id_color_palette_aux6') }, + { index: 6, color: $r('sys.color.ohos_id_color_palette_aux6') } ]; build() { GridRow() { - ForEach(this.elements, (item: Obj) => { - // If the values of the three parameters are not configured at the md breakpoint, - // they will inherit the values from the sm breakpoint. + ForEach(this.elements, (item: ColorArr) => { + // If the values of the three parameters are not configured at the md breakpoint, they will inherit the values from the sm breakpoint. GridCol({ - span: { sm: 4, lg: 3 }, offset: { sm: 2, lg: 1 }, + span: { sm: 4, lg: 3 }, + offset: { sm: 2, lg: 1 }, order: { sm: (6 - item.index), lg: item.index } }) { Row() { - Text('' + item.index) + Text(`${item.index}`) .fontSize(24) } .justifyContent(FlexAlign.Center) .backgroundColor(item.color) .height(30) - .width('100%') } - }) + }, (item: ColorArr, index: number) => JSON.stringify(item) + index) } } } -// [End GridRowSample8] \ No newline at end of file +// End GridRowSample8 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample9.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample9.ets index e696873eb419dbff8a28b936e6a6fd85887769b7..8683c5f7534114d275feaafda6f23fbb52ec65b0 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample9.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/gridRow/gridRow/GridRowSample9.ets @@ -13,40 +13,39 @@ * limitations under the License. */ -// [Start GridRowSample9] -class Obj { - public index: number = 1; - public color: Resource = $r('sys.color.ohos_id_color_palette_aux1'); -} +import { ColorArr } from '../../../common/ColorEntity'; +// Start GirdRowSample9 @Entry @Component struct GridRowSample9 { - private elements: Obj[] = [ + private elements: ColorArr[] = [ { index: 1, color: $r('sys.color.ohos_id_color_palette_aux1') }, { index: 2, color: $r('sys.color.ohos_id_color_palette_aux2') }, { index: 3, color: $r('sys.color.ohos_id_color_palette_aux3') }, { index: 4, color: $r('sys.color.ohos_id_color_palette_aux4') }, { index: 5, color: $r('sys.color.ohos_id_color_palette_aux5') }, - { index: 6, color: $r('sys.color.ohos_id_color_palette_aux6') }, + { index: 6, color: $r('sys.color.ohos_id_color_palette_aux6') } ]; build() { GridRow() { - GridCol({ span: { sm: 12, md: 10, lg: 8 }, offset: { sm: 0, md: 1, lg: 2 } }) { + GridCol({ + span: { sm: 12, md: 10, lg: 8 }, + offset: { sm: 0, md: 1, lg: 2 } + }) { GridRow() { - ForEach(this.elements, (item: Obj) => { + ForEach(this.elements, (item : ColorArr) => { GridCol({ span: { sm: 6, md: 4, lg: 3 } }) { Row() { - Text('' + item.index) + Text(`${item.index}`) .fontSize(24) } .justifyContent(FlexAlign.Center) .backgroundColor(item.color) .height(30) - .width('100%') } - }) + }, (item: ColorArr, index: number) => JSON.stringify(item) + index) } .backgroundColor('#19000000') .height('100%') @@ -54,4 +53,4 @@ struct GridRowSample9 { } } } -// [End GridRowSample9] \ No newline at end of file +// End GirdRowSample9 \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/breakpoint/Breakpoint.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/breakpoint/Breakpoint.ets index 77f5059b54e8a4a9b13b5fe7403e225d7579ef72..f33854eb11672983205dfb6d1a86c0e89b5ccc65 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/breakpoint/Breakpoint.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/breakpoint/Breakpoint.ets @@ -13,10 +13,9 @@ * limitations under the License. */ -// [Start Breakpoint] -// common/breakpointsystem.ets -import { mediaquery } from '@kit.ArkUI'; +import { mediaquery } from "@kit.ArkUI"; +// Start MediaQuery export type BreakpointType = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; export interface Breakpoint { @@ -62,7 +61,8 @@ export class BreakpointSystem { } else { condition = `(${breakpoint.size}vp<=width<${this.breakpoints[index + 1].size}vp)`; } - breakpoint.mediaQueryListener = mediaquery.matchMediaSync(condition); + let uiContext = AppStorage.get('uiContext') as UIContext; + breakpoint.mediaQueryListener = uiContext.getMediaQuery().matchMediaSync(condition); if (breakpoint.mediaQueryListener.matches) { this.updateAllState(breakpoint.name); } @@ -89,12 +89,12 @@ export class BreakpointSystem { } export interface BreakpointOptions { - xs?: T - sm?: T - md?: T - lg?: T - xl?: T - xxl?: T + xs?: T; + sm?: T; + md?: T; + lg?: T; + xl?: T; + xxl?: T; } export class BreakpointState { @@ -127,5 +127,4 @@ export class BreakpointState { } } } -// [End Breakpoint] - +// End MediaQuery \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/breakpoint/BreakpointSample.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/breakpoint/BreakpointSample.ets index 2b0e70982a5f9db15cff316e56784f02f4310ff1..9630ba109f3ee416cf79890f443dada7855ff6f9 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/breakpoint/BreakpointSample.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/breakpoint/BreakpointSample.ets @@ -13,7 +13,8 @@ * limitations under the License. */ -import { BreakpointSystem, BreakpointState } from './Breakpoint' +// Start BreakpointSample +import { BreakpointSystem, BreakpointState } from './Breakpoint'; @Entry @Component @@ -26,15 +27,15 @@ struct BreakpointSample { }); aboutToAppear() { - BreakpointSystem.getInstance().attach(this.compStr) - BreakpointSystem.getInstance().attach(this.compImg) - BreakpointSystem.getInstance().start() + BreakpointSystem.getInstance().attach(this.compStr); + BreakpointSystem.getInstance().attach(this.compImg); + BreakpointSystem.getInstance().start(); } aboutToDisappear() { - BreakpointSystem.getInstance().detach(this.compStr) - BreakpointSystem.getInstance().detach(this.compImg) - BreakpointSystem.getInstance().stop() + BreakpointSystem.getInstance().detach(this.compStr); + BreakpointSystem.getInstance().detach(this.compImg); + BreakpointSystem.getInstance().stop(); } build() { @@ -53,4 +54,5 @@ struct BreakpointSample { .width('100%') .height('100%') } -} \ No newline at end of file +} +// End BreakpointSample \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/mediaQuery/MediaQuerySample.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/mediaQuery/MediaQuerySample.ets index 66179fab28f5291012e816a3beda356a05583b18..b2598e35f41f40709ccff6f4ef676b95f32a2300 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/mediaQuery/MediaQuerySample.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/responsiveLayout/mediaQuery/MediaQuerySample.ets @@ -13,48 +13,40 @@ * limitations under the License. */ -// [Start MediaQuerySample] -// MediaQuerySample.ets -import { BreakpointState, BreakpointSystem } from '../breakpoint/Breakpoint'; +import { BreakpointSystem, BreakPointType } from '../../../common/BreakpointSystem'; @Entry @Component struct MediaQuerySample { - @State compStr: BreakpointState = BreakpointState.of({ sm: "sm", md: "md", lg: "lg" }); - @State compImg: BreakpointState = BreakpointState.of({ - sm: $r('app.media.sm'), - md: $r('app.media.md'), - lg: $r('app.media.lg') - }); + @StorageProp('currentBreakpoint') currentBreakpoint: string = 'md'; + private breakpointSystem: BreakpointSystem = new BreakpointSystem(); aboutToAppear() { - BreakpointSystem.getInstance().attach(this.compStr); - BreakpointSystem.getInstance().attach(this.compImg); - BreakpointSystem.getInstance().start(); + this.breakpointSystem.register(); } aboutToDisappear() { - BreakpointSystem.getInstance().detach(this.compStr); - BreakpointSystem.getInstance().detach(this.compImg); - BreakpointSystem.getInstance().stop(); + this.breakpointSystem.unregister(); } build() { - Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { - Column() + Column() { + Image(new BreakPointType({ + sm: $r('app.media.sm'), + md: $r('app.media.md'), + lg: $r('app.media.lg') + }) + .getValue(this.currentBreakpoint)) .height(100) .width(100) - .backgroundImage(this.compImg.value) - .backgroundImagePosition(Alignment.Center) - .backgroundImageSize(ImageSize.Contain) + .objectFit(ImageFit.Contain) - - Text(this.compStr.value) + Text(this.currentBreakpoint) .fontSize(24) .margin(10) } .width('100%') .height('100%') + .justifyContent(FlexAlign.Center) } -} -// [End MediaQuerySample] \ No newline at end of file +} \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/typicalScene/multiScene/pages/MultiScene.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/typicalScene/multiScene/pages/MultiScene.ets index 168f304e65f27b37e6ea1157939a717d25ac48cd..daa35369226431cd011cbedb2b5fd6609f3ea8a1 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/typicalScene/multiScene/pages/MultiScene.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/typicalScene/multiScene/pages/MultiScene.ets @@ -25,7 +25,7 @@ struct DiversionSample { @State barWidth: number = -1 @State barHeight: number = -1 @State currentIndex: number = 0 - private listener = mediaquery.matchMediaSync('(orientation: landscape)') + private listener = this.getUIContext().getMediaQuery().matchMediaSync('(orientation: landscape)'); // 监听横竖屏 onPortrait(mediaQueryResult: mediaquery.MediaQueryResult) { @@ -41,12 +41,13 @@ struct DiversionSample { } aboutToAppear() { - this.listener.on('change', (mediaQueryResult:mediaquery.MediaQueryResult) => { + this.listener.on('change', (mediaQueryResult: mediaquery.MediaQueryResult) => { this.onPortrait(mediaQueryResult); }) //绑定回调函数 } - @Builder NavigationTitle() { + @Builder + NavigationTitle() { Column() { Text($r('app.string.multiScene_header_title')) .fontColor('#182431') @@ -62,7 +63,8 @@ struct DiversionSample { }.alignItems(HorizontalAlign.Start) } - @Builder TabBuilder(title: Resource, targetIndex: number, selectedImg: Resource, normalImg: Resource) { + @Builder + TabBuilder(title: Resource, targetIndex: number, selectedImg: Resource, normalImg: Resource) { Column() { Image(this.currentIndex === targetIndex ? selectedImg : normalImg) .size({ width: 25, height: 25 }) @@ -85,25 +87,29 @@ struct DiversionSample { TabContent() { HomePage() } - .tabBar(this.TabBuilder($r('app.string.multiScene_tabs_home'), 0, $r('app.media.ic_public_home_select'), $r('app.media.ic_public_home'))) + .tabBar(this.TabBuilder($r('app.string.multiScene_tabs_home'), 0, $r('app.media.ic_public_home_select'), + $r('app.media.ic_public_home'))) // 应用 TabContent() { Applications() } - .tabBar(this.TabBuilder($r('app.string.multiScene_tabs_app'), 1, $r('app.media.ic_public_albums_select'), $r('app.media.ic_public_albums'))) + .tabBar(this.TabBuilder($r('app.string.multiScene_tabs_app'), 1, $r('app.media.ic_public_albums_select'), + $r('app.media.ic_public_albums'))) // 播放 TabContent() { Play() } - .tabBar(this.TabBuilder($r('app.string.multiScene_tabs_play'), 2, $r('app.media.ic_gallery_template_select'), $r('app.media.ic_gallery_template'))) + .tabBar(this.TabBuilder($r('app.string.multiScene_tabs_play'), 2, + $r('app.media.ic_gallery_template_select'), $r('app.media.ic_gallery_template'))) // 我的 TabContent() { Text($r('app.string.multiScene_my_content')).fontSize(30) } - .tabBar(this.TabBuilder($r('app.string.multiScene_tabs_me'), 3, $r('app.media.ic_public_contacts_select'), $r('app.media.ic_public_contacts'))) + .tabBar(this.TabBuilder($r('app.string.multiScene_tabs_me'), 3, $r('app.media.ic_public_contacts_select'), + $r('app.media.ic_public_contacts'))) } .vertical(this.isVertical) .barWidth(this.barWidth) diff --git a/AdaptiveCapabilities/entry/src/main/ets/pages/typicalScene/repeat/RepeatSample.ets b/AdaptiveCapabilities/entry/src/main/ets/pages/typicalScene/repeat/RepeatSample.ets index 64f0dac15d1845f03840fcef7f3d687ab09566be..8c9ff078175f795945c835124b330d7ab375c654 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/pages/typicalScene/repeat/RepeatSample.ets +++ b/AdaptiveCapabilities/entry/src/main/ets/pages/typicalScene/repeat/RepeatSample.ets @@ -13,15 +13,15 @@ * limitations under the License. */ -import mediaquery from '@ohos.mediaquery' +import { mediaquery } from '@kit.ArkUI' @Entry @Component struct RepeatSample { @State isWidescreen: boolean = false @State currentBreakpoint: string = 'sm' - private listener: mediaquery.MediaQueryListener = mediaquery.matchMediaSync('(width>1200)') - onWidthChange = (mediaQueryResult:mediaquery.MediaQueryResult) => { + private listener: mediaquery.MediaQueryListener = this.getUIContext().getMediaQuery().matchMediaSync('(width>1200)'); + onWidthChange = (mediaQueryResult: mediaquery.MediaQueryResult) => { if (mediaQueryResult.matches) { this.isWidescreen = true } else { @@ -92,7 +92,12 @@ struct RepeatItemContent { .alignItems(HorizontalAlign.Start) .justifyContent(FlexAlign.SpaceAround) } - .padding({ top: 13, bottom: 13, left: 13, right: 37 }) + .padding({ + top: 13, + bottom: 13, + left: 13, + right: 37 + }) .height(70) .backgroundColor('#FFFFFF') .margin({ bottom: 12 }) diff --git a/AdaptiveCapabilities/entry/src/main/module.json5 b/AdaptiveCapabilities/entry/src/main/module.json5 index 3151060d0668396989568b39b28443bdf38c9ff7..caa560b57deb58722e84fd61a4581426043e7b8a 100644 --- a/AdaptiveCapabilities/entry/src/main/module.json5 +++ b/AdaptiveCapabilities/entry/src/main/module.json5 @@ -17,7 +17,6 @@ "module": { "name": "entry", "type": "entry", - "srcEntrance": "./ets/Application/AbilityStage.ts", "description": "$string:entry_desc", "mainElement": "MainAbility", "deviceTypes": [ @@ -27,11 +26,10 @@ "deliveryWithInstall": true, "installationFree": false, "pages": "$profile:main_pages", - "uiSyntax": "ets", "abilities": [ { "name": "MainAbility", - "srcEntry": "./ets/MainAbility/MainAbility.ts", + "srcEntry": "./ets/MainAbility/MainAbility.ets", "description": "$string:MainAbility_desc", "icon": "$media:icon", "label": "$string:MainAbility_label", diff --git a/AdaptiveCapabilities/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts b/AdaptiveCapabilities/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts deleted file mode 100644 index 9d3af21746c45c081c977edf18d029902775c67b..0000000000000000000000000000000000000000 --- a/AdaptiveCapabilities/entry/src/ohosTest/ets/TestRunner/OpenHarmonyTestRunner.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2023 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 '@ohos.hilog'; -import TestRunner from '@ohos.application.testRunner'; -import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; - -let abilityDelegator; -let abilityDelegatorArguments; - -function translateParamsToString(parameters) { - const keySet = new Set([ - '-s class', '-s notClass', '-s suite', '-s it', - '-s level', '-s testType', '-s size', '-s timeout', - '-s dryRun' - ]) - let targetParams = ''; - for (const key in parameters) { - if (keySet.has(key)) { - targetParams = `${targetParams} ${key} ${parameters[key]}` - } - } - return targetParams.trim() -} - -async function onAbilityCreateCallback() { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'onAbilityCreateCallback'); -} - -async function addAbilityMonitorCallback(err: any) { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? ''); -} - -export default class OpenHarmonyTestRunner implements TestRunner { - constructor() { - } - - onPrepare() { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare '); - } - - async onRun() { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun run'); - abilityDelegatorArguments = abilityDelegatorRegistry.getArguments(); - abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); - let testAbilityName = abilityDelegatorArguments.bundleName + '.TestAbility'; - let lMonitor = { - abilityName: testAbilityName, - onAbilityCreate: onAbilityCreateCallback, - }; - abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback); - let cmd = 'aa start -d 0 -a TestAbility' + ' -b ' + abilityDelegatorArguments.bundleName; - cmd += ' ' + translateParamsToString(abilityDelegatorArguments.parameters); - let debug = abilityDelegatorArguments.parameters['-D']; - if (debug == 'true') { - cmd += ' -D' - }; - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', 'cmd : %{public}s', cmd); - abilityDelegator.executeShellCommand(cmd, - (err: any, d: any) => { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', 'executeShellCommand : err : %{public}s', JSON.stringify(err) ?? ''); - hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.stdResult ?? ''); - hilog.info(0x0000, 'testTag', 'executeShellCommand : data : %{public}s', d.exitCode ?? ''); - }) - hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner onRun end'); - } -} \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/ohosTest/ets/test/Ability.test.ets b/AdaptiveCapabilities/entry/src/ohosTest/ets/test/Ability.test.ets deleted file mode 100644 index ab60a554512a23d20b84fd9f090803251b2d04f8..0000000000000000000000000000000000000000 --- a/AdaptiveCapabilities/entry/src/ohosTest/ets/test/Ability.test.ets +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright (c) 2023 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 { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium' -import { Driver, ON } from '@ohos.UiTest' -import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry' -import hilog from '@ohos.hilog' -import resmgr from '@ohos.resourceManager'; - -const TAG = '[Sample_AdaptiveCapabilities]' -const DOMAIN = 0xF811 -const BUNDLE = 'AdaptiveCapabilities_' - -let driver: Driver = Driver.create() -//通过id验证有没有这个组件 有的话点击一下 -async function checkButtonAndClickWithID(text: string) { - let idName = text - await driver.assertComponentExist(ON.id(idName)) - let button = await driver.findComponent(ON.id(idName)) - await button.click() - await driver.delayMs(1000) -} -//通过text验证有没有这个组件 有的话点击一下 -async function checkButtonAndClickWithText(text: string) { - let textName = text - await driver.assertComponentExist(ON.text(textName)) - let button = await driver.findComponent(ON.text(textName)) - await button.click() - await driver.delayMs(1000) -} - -// 获取AbilityDelegator -let abilityDelegatorRegistry = AbilityDelegatorRegistry.getAbilityDelegator(); -// 启动后获取app上下文 -let context: Context; -// 启动后获取resourceManager -let manager: resmgr.ResourceManager; - -async function checkRadioAndClickWithID(text: string) { - await driver.assertComponentExist(ON.id(text)); - let component = await driver.findComponent(ON.id(text)); - await component.click(); -} - -async function checkRadioAndClickWithText(text: string) { - await driver.assertComponentExist(ON.text(text)); - let component = await driver.findComponent(ON.text(text)); - await component.click(); -} - -let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() - -async function getResourceString(resource: Resource): Promise { - let manage = abilityDelegator.getAppContext().resourceManager - let text = await manage.getStringValue(resource) - return text -} - -export default function appTest() { - describe('ActsAbilityTest', () => { - /** - * 打开应用 - */ - it(BUNDLE + 'StartAbility_001 begin', 0, async (done: Function) => { - hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 begin') - let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator(); - try { - await abilityDelegator.startAbility({ - bundleName: 'ohos.samples.AdaptiveCapabilities', - abilityName: 'MainAbility' - }); - context = abilityDelegatorRegistry.getAppContext(); - manager = context.resourceManager; - done(); - } catch (err) { - expect(0).assertEqual(err.code); - done(); - } - hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end') - }) - - /** - * 自适应布局 (目前坐标只适用于RK3568) - */ - it(BUNDLE + 'CreateAdaptiveCapabilitiesOneFunction_001', 0, async ()=> { - // create UiDriver - hilog.info(DOMAIN, TAG, BUNDLE + 'CreateAdaptiveCapabilitiesOneFunction_001 begin') - let driver = Driver.create() - await driver.delayMs(1000) - // 点击自适应布局 - await checkButtonAndClickWithID('AtomicLayoutCapabilityIndex') - // 点击拉伸能力1 - await checkButtonAndClickWithID('FlexibleCapability1') - // slider滑动 - await driver.swipe(410, 1017, 360, 1017, 200) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 点击拉伸能力2 - await checkButtonAndClickWithID('FlexibleCapability2') - // 打开switch - await driver.assertComponentExist(ON.type('Toggle')) - let toggle = await driver.findComponent(ON.type('Toggle')) - await toggle.click() - await driver.delayMs(1000) - // slider滑动 - await driver.swipe(410, 1017, 360, 1017, 200) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 点击缩放能力 - await checkButtonAndClickWithID('ScaleCapability') - // slider1滑动 - await driver.swipe(410, 1017, 360, 1017, 200) - await driver.delayMs(1000) - // slider2滑动 - await driver.swipe(410, 1017, 360, 1017, 200) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 点击隐藏能力 - await checkButtonAndClickWithID('HiddenCapability') - // slider滑动 - await driver.swipe(410, 1017, 360, 1017, 200) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 点击折行能力 - await checkButtonAndClickWithID('WrapCapability') - // slider滑动 - await driver.swipe(410, 1017, 360, 1017, 200) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 点击均分能力 - await checkButtonAndClickWithID('EquipartitionCapability') - // slider滑动 - await driver.swipe(410, 1017, 360, 1017, 200) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 向下滑动 - await driver.swipe(100, 500, 20, 20) - await driver.delayMs(1000) - // 点击占比能力 - await checkButtonAndClickWithID('ProportionCapability') - // slider滑动 - await driver.swipe(410, 1017, 360, 1017, 200) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 点击延伸能力1 - await checkButtonAndClickWithID('ExtensionCapability1') - // scroll 应用滑动 - await driver.swipe(360, 639, 0, 639, 200) - await driver.delayMs(1000) - // slider滑动 - await driver.swipe(410, 1017, 360, 1017, 200) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 点击延伸能力2 - await checkButtonAndClickWithID('ExtensionCapability2') - // scroll 应用滑动 - await driver.swipe(360, 639, 0, 639, 200) - await driver.delayMs(1000) - // slider滑动 - await driver.swipe(410, 1017, 360, 1017, 200) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - hilog.info(DOMAIN, TAG, BUNDLE + 'CreateAdaptiveCapabilitiesOneFunction_001 end') - }) - - /** - * 响应式布局 (目前坐标只适用于RK3568) - */ - it(BUNDLE + 'CreateAdaptiveCapabilitiesTwoFunction_001', 0, async () => { - // create UiDriver - hilog.info(DOMAIN, TAG, BUNDLE + 'CreateAdaptiveCapabilitiesTwoFunction_001 begin') - let driver = Driver.create() - await driver.delayMs(1000) - // 点击响应式布局 - await checkButtonAndClickWithID('ResponsiveLayoutIndex') - // 点击断点 - await checkButtonAndClickWithID('BreakpointSample') - await driver.pressBack() - await driver.delayMs(1000) - // 点击媒体查询 - await checkButtonAndClickWithID('MediaQuerySample') - await driver.pressBack() - await driver.delayMs(1000) - // 点击栅格布局 - await checkButtonAndClickWithID('GridRowLayoutIndex') - // 点击栅格断点1 - await checkButtonAndClickWithID('GridRowSample1') - await driver.pressBack() - await driver.delayMs(1000) - // 点击栅格断点2 - await checkButtonAndClickWithID('GridRowSample2') - await driver.pressBack() - await driver.delayMs(1000) - // 点击栅格columns和gutter - await checkButtonAndClickWithID('GridRowSample3') - let checkBtn = await driver.findComponent(ON.type('GridCol')); - await checkBtn.click(); - await driver.pressBack() - await driver.delayMs(1000) - // 点击栅格margin - await checkButtonAndClickWithID('GridRowSample4') - await driver.pressBack() - await driver.delayMs(1000) - // 点击栅格span - await checkButtonAndClickWithID('GridRowSample5') - await driver.pressBack() - await driver.delayMs(1000) - // 点击栅格offset - await checkButtonAndClickWithID('GridRowSample6') - await driver.pressBack() - await driver.delayMs(1000) - // 点击栅格order - await checkButtonAndClickWithID('GridRowSample7') - await driver.pressBack() - await driver.delayMs(1000) - // 向下滑动 - await driver.swipe(100, 500, 20, 20) - await driver.delayMs(1000) - // 点击栅格span/offset/order继承性 - await checkButtonAndClickWithID('GridRowSample8') - await driver.pressBack() - await driver.delayMs(1000) - // 点击栅格嵌套 - await checkButtonAndClickWithID('GridRowSample9') - await driver.pressBack() - await driver.delayMs(1000) - // 点击栅格对齐 - await checkButtonAndClickWithID('GridRowSample10'); - await checkRadioAndClickWithID('rdo11'); - await checkRadioAndClickWithID('rdo22'); - await checkRadioAndClickWithID('rdo33'); - await checkRadioAndClickWithID('rdo41'); - await driver.pressBack(); - await driver.delayMs(1000); - await driver.pressBack() - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - hilog.info(DOMAIN, TAG, BUNDLE + 'CreateAdaptiveCapabilitiesTwoFunction_001 end') - }) - - /** - * 典型布局场景 (目前坐标只适用于RK3568) - */ - it(BUNDLE + 'CreateAdaptiveCapabilitiesThreeFunction_001', 0, async () => { - // create UiDriver - hilog.info(DOMAIN, TAG, BUNDLE + 'CreateAdaptiveCapabilitiesThreeFunction_001 begin') - let driver = Driver.create() - await driver.delayMs(1000) - // 点击典型布局场景 - await checkButtonAndClickWithID('TypicalSceneIndex') - // 点击挪移布局 - await checkButtonAndClickWithID('DiversionSample') - await driver.pressBack() - await driver.delayMs(1000) - // 点击重复布局 - await checkButtonAndClickWithID('RepeatSample') - // scroll 滑动 - await driver.swipe(360, 640, 360, 0, 200) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 点击缩进布局 - await checkButtonAndClickWithID('IndentationSample') - await driver.pressBack() - await driver.delayMs(1000) - // 点击顶部布局 - await checkButtonAndClickWithID('HeaderSample') - await driver.pressBack() - await driver.delayMs(1000) - await driver.pressBack(); - await driver.delayMs(1000); - // 点击广告栏 - await checkButtonAndClickWithID('BannerSample') - // swiper滑动 - await driver.swipe(360, 222, 0, 222, 1000) - await driver.swipe(360, 222, 0, 222, 1000) - await driver.swipe(360, 222, 0, 222, 1000) - await driver.swipe(360, 222, 0, 222, 1000) - await driver.swipe(360, 222, 0, 222, 1000) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 点击操作入口 - await checkButtonAndClickWithID('OperationEntriesSample') - await driver.swipe(360, 150, 0, 150, 200) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 向下滑动 - await driver.swipe(100, 500, 20, 20) - await driver.delayMs(1000) - // 点击页签布局 - await checkButtonAndClickWithID('TabsSample') - // 点击排行榜 - await checkButtonAndClickWithText(await getResourceString($r('app.string.tabBar2'))) - // 点击我的 - await checkButtonAndClickWithText(await getResourceString($r('app.string.tabBar3'))) - await driver.pressBack() - await driver.delayMs(1000) - // 点击大图浏览 - await checkButtonAndClickWithID('BigImageSample') - await driver.pressBack() - await driver.delayMs(1000) - // 点击多列列表 - await checkButtonAndClickWithID('MultiLaneListSample') - // 向下滑动 - await driver.swipe(100, 500, 20, 20) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 点击网格视图 - await checkButtonAndClickWithID('ResponsiveGridSample') - // 向下滑动 - await driver.swipe(100, 500, 20, 20) - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - // 点击侧边栏 - await checkButtonAndClickWithID('SidebarSample') - await driver.pressBack() - await driver.delayMs(1000) - //向下下滑 - await driver.swipe(360, 900, 360, 200, 2000) - //点击一多典型场景 - await checkButtonAndClickWithID('multiScene') - //上下滑动list - await driver.swipe(360, 1100, 360, 900, 200) - //左右滑动swiper - await driver.swipe(700, 300, 20, 300, 1000) - await checkButtonAndClickWithText(await getResourceString($r('app.string.multiScene_tabs_app'))) - //上下滑动应用列表 - await driver.swipe(360, 1100, 360, 900, 200) - await checkButtonAndClickWithText(await getResourceString($r('app.string.multiScene_tabs_play'))) - await checkButtonAndClickWithText(await getResourceString($r('app.string.multiScene_tabs_me'))) - await driver.swipe(20, 300, 700, 300, 1000) - await driver.swipe(20, 300, 700, 300, 1000) - await driver.swipe(20, 300, 700, 300, 1000) - await driver.pressBack() - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - hilog.info(DOMAIN, TAG, BUNDLE + 'CreateAdaptiveCapabilitiesThreeFunction_001 end') - }) - - /** - * 资源文件使用 - */ - it(BUNDLE + 'CreateAdaptiveCapabilitiesFourFunction_001', 0, async () => { - // create UiDriver - hilog.info(DOMAIN, TAG, BUNDLE + 'CreateAdaptiveCapabilitiesFourFunction_001 begin') - let driver = Driver.create() - await driver.delayMs(1000) - // 点击资源文件使用 - await checkButtonAndClickWithID('ResourceQualifier') - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - hilog.info(DOMAIN, TAG, BUNDLE + 'CreateAdaptiveCapabilitiesFourFunction_001 end') - }) - - /** - * 交互归一能力 - */ - it(BUNDLE + 'CreateAdaptiveCapabilitiesFiveFunction_001', 0, async () => { - // create UiDriver - hilog.info(DOMAIN, TAG, BUNDLE + 'CreateAdaptiveCapabilitiesFiveFunction_001 begin') - let driver = Driver.create() - await driver.delayMs(1000) - // 点击交互归一能力 - await checkButtonAndClickWithID('InteractionNormCapability') - await driver.delayMs(1000) - await driver.pressBack() - await driver.delayMs(1000) - hilog.info(DOMAIN, TAG, BUNDLE + 'CreateAdaptiveCapabilitiesFiveFunction_001 end') - }) - }) -} - diff --git a/AdaptiveCapabilities/entry/src/ohosTest/ets/testability/TestAbility.ets b/AdaptiveCapabilities/entry/src/ohosTest/ets/testability/TestAbility.ets deleted file mode 100644 index ff8fcf96f026a675d81fbeaf93cd460c21345993..0000000000000000000000000000000000000000 --- a/AdaptiveCapabilities/entry/src/ohosTest/ets/testability/TestAbility.ets +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2023 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 '@ohos.hilog'; -import UIAbility from '@ohos.app.ability.UIAbility' -import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry' -import { Hypium } from '@ohos/hypium' -import testsuite from '../test/List.test' -import Window from '@ohos.window' -import Want from '@ohos.app.ability.Want'; -import AbilityConstant from '@ohos.app.ability.AbilityConstant'; - -export default class TestAbility extends UIAbility { - onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate'); - hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? ''); - hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:'+ JSON.stringify(launchParam) ?? ''); - let abilityDelegator: AbilityDelegatorRegistry.AbilityDelegator; - abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator() - let abilityDelegatorArguments: AbilityDelegatorRegistry.AbilityDelegatorArgs; - abilityDelegatorArguments = AbilityDelegatorRegistry.getArguments() - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!'); - Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite) - } - - onDestroy() { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy'); - } - - onWindowStageCreate(windowStage: Window.WindowStage) { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate'); - windowStage.loadContent('testability/pages/Index', (err, data) => { - if (err.code) { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.ERROR); - hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); - return; - } - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? ''); - }); - } - - onWindowStageDestroy() { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy'); - } - - onForeground() { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground'); - } - - onBackground() { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground'); - } -} \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/ohosTest/resources/base/element/string.json b/AdaptiveCapabilities/entry/src/ohosTest/resources/base/element/string.json deleted file mode 100644 index e602e87b1fed50cade73ad86f2a6c0788e1c7a18..0000000000000000000000000000000000000000 --- a/AdaptiveCapabilities/entry/src/ohosTest/resources/base/element/string.json +++ /dev/null @@ -1,300 +0,0 @@ -{ - "string": [ - { - "name": "entry_desc", - "value": "description" - }, - { - "name": "MainAbility_desc", - "value": "description" - }, - { - "name": "MainAbility_label", - "value": "eTSAdaptiveCapabilities" - }, - { - "name": "module_test_desc", - "value": "test ability description" - }, - { - "name": "TestAbility_desc", - "value": "the test ability" - }, - { - "name": "TestAbility_label", - "value": "test label" - }, - { - "name": "my_string", - "value": "phone" - }, - { - "name": "home_title", - "value": "Page development-Adaptive Capabilities" - }, - { - "name": "resource_qualifier", - "value": "Resource qualifier" - }, - { - "name": "atomic_capability", - "value": "Atomic layout capability" - }, - { - "name": "responsive_layout", - "value": "Responsive layout" - }, - { - "name": "flex_capability_first", - "value": "Flexible capability first" - }, - { - "name": "flex_capability_second", - "value": "Flexible capability second" - }, - { - "name": "scaling_capability", - "value": "Scaling capability" - }, - { - "name": "hidden_capability", - "value": "Hidden capability" - }, - { - "name": "wrap_capability", - "value": "Wrap capability" - }, - { - "name": "equally_capability", - "value": "Equally capability" - }, - { - "name": "percentage_capability", - "value": "Percentage capability" - }, - { - "name": "extension_capability_first", - "value": "Extension capacity first" - }, - { - "name": "extension_capability_second", - "value": "Extension capacity second" - }, - { - "name": "healthy_use_phone", - "value": "Healthy use of phone" - }, - { - "name": "media_query", - "value": "Media query" - }, - { - "name": "grid_layout", - "value": "Grid layout" - }, - { - "name": "grid_layout1", - "value": "Grid breakpoint 1" - }, - { - "name": "grid_layout2", - "value": "Grid breakpoint 2" - }, - { - "name": "grid_layout3", - "value": "Grid columns and gutter" - }, - { - "name": "grid_layout4", - "value": "Grid margin" - }, - { - "name": "grid_layout5", - "value": "Grid span" - }, - { - "name": "grid_layout6", - "value": "Grid offset" - }, - { - "name": "grid_layout7", - "value": "Grid order" - }, - { - "name": "grid_layout8", - "value": "Grid inheritance of span/offset/order" - }, - { - "name": "grid_layout9", - "value": "Grid nested" - }, - { - "name": "grid_layout10", - "value": "Grid alignItem" - }, - { - "name": "typical_scenario", - "value": "Typical scenario" - }, - { - "name": "diversion_layout", - "value": "Diversion layout" - }, - { - "name": "repeat_layout", - "value": "Repeat layout" - }, - { - "name": "indentation_layout", - "value": "Indentation layout" - }, - { - "name": "header", - "value": "header" - }, - { - "name": "banner", - "value": "banner" - }, - { - "name": "operationEntries", - "value": "operation entries" - }, - { - "name": "tabs", - "value": "tabs layout" - }, - { - "name": "bigImage", - "value": "big image" - }, - { - "name": "multiLaneList", - "value": "multi lane list" - }, - { - "name": "grid", - "value": "grid layout" - }, - { - "name": "aside", - "value": "aside" - }, - { - "name": "user_improvement", - "value": "User Experience Improvement Program" - }, - { - "name": "user_improvement_tips", - "value": "The User Experience Improvement Program improves huawei's product and service quality through system, application analysis, and fault diagnosis." - }, - { - "name": "show_app_name", - "value": "App name" - }, - { - "name": "left", - "value": "Left" - }, - { - "name": "center", - "value": "Center" - }, - { - "name": "right", - "value": "Right" - }, - { - "name": "portrait", - "value": "Portrait" - }, - { - "name": "landscape", - "value": "Landscape" - }, - { - "name": "recommended", - "value": "recommended" - }, - { - "name": "operation1", - "value": "Private FM" - }, - { - "name": "operation2", - "value": "Singer" - }, - { - "name": "operation3", - "value": "Playlist" - }, - { - "name": "operation4", - "value": "Ranking List" - }, - { - "name": "operation5", - "value": "Hot" - }, - { - "name": "operation6", - "value": "Sports Music" - }, - { - "name": "operation7", - "value": "Music FM" - }, - { - "name": "operation8", - "value": "Welfare" - }, - { - "name": "playlist_collection", - "value": "Playlist Collection" - }, - { - "name": "tabBar1", - "value": "Home" - }, - { - "name": "tabBar2", - "value": "Ranking List" - }, - { - "name": "tabBar3", - "value": "My" - }, - { - "name": "breakpoint", - "value": "breakpoint" - }, - { - "name": "Radio_GridRow_All_LCR", - "value": "All GridColl L-C-R" - }, - { - "name": "Radio_GridRow_All_TMB", - "value": "All GridColl T-M-B" - }, - { - "name": "Radio_GridRow_Sg_LCR", - "value": "Second GridCol L-C-R" - }, - { - "name": "Radio_GridRow_Sg_TMB", - "value": "Second GridCol T-M-B" - }, - { - "name": "multiScene_tabs_app", - "value": "apps" - }, - { - "name": "multiScene_tabs_play", - "value": "play" - }, - { - "name": "multiScene_tabs_me", - "value": "me" - } - ] -} \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/ohosTest/resources/base/profile/test_pages.json b/AdaptiveCapabilities/entry/src/ohosTest/resources/base/profile/test_pages.json deleted file mode 100644 index b7e7343cacb32ce982a45e76daad86e435e054fe..0000000000000000000000000000000000000000 --- a/AdaptiveCapabilities/entry/src/ohosTest/resources/base/profile/test_pages.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "src": [ - "testability/pages/Index" - ] -} diff --git a/AdaptiveCapabilities/entry/src/ohosTest/resources/en/element/string.json b/AdaptiveCapabilities/entry/src/ohosTest/resources/en/element/string.json deleted file mode 100644 index c3567a030851d3f1449e1edb174562a392280510..0000000000000000000000000000000000000000 --- a/AdaptiveCapabilities/entry/src/ohosTest/resources/en/element/string.json +++ /dev/null @@ -1,300 +0,0 @@ -{ - "string": [ - { - "name": "entry_desc", - "value": "description" - }, - { - "name": "MainAbility_desc", - "value": "description" - }, - { - "name": "MainAbility_label", - "value": "eTSAdaptiveCapabilities" - }, - { - "name": "module_test_desc", - "value": "test ability description" - }, - { - "name": "TestAbility_desc", - "value": "the test ability" - }, - { - "name": "TestAbility_label", - "value": "test label" - }, - { - "name": "my_string", - "value": "phone" - }, - { - "name": "home_title", - "value": "Page development-Adaptive Capabilities" - }, - { - "name": "resource_qualifier", - "value": "Resource qualifier" - }, - { - "name": "atomic_capability", - "value": "Atomic layout capability" - }, - { - "name": "responsive_layout", - "value": "Responsive layout" - }, - { - "name": "flex_capability_first", - "value": "Flexible capability first" - }, - { - "name": "flex_capability_second", - "value": "Flexible capability second" - }, - { - "name": "scaling_capability", - "value": "Scaling capability" - }, - { - "name": "hidden_capability", - "value": "Hidden capability" - }, - { - "name": "wrap_capability", - "value": "Wrap capability" - }, - { - "name": "equally_capability", - "value": "Equally capability" - }, - { - "name": "percentage_capability", - "value": "Percentage capability" - }, - { - "name": "extension_capability_first", - "value": "Extension capacity first" - }, - { - "name": "extension_capability_second", - "value": "Extension capacity second" - }, - { - "name": "healthy_use_phone", - "value": "Healthy use of phone" - }, - { - "name": "media_query", - "value": "Media query" - }, - { - "name": "grid_layout", - "value": "Grid layout" - }, - { - "name": "grid_layout1", - "value": "Grid breakpoint 1" - }, - { - "name": "grid_layout2", - "value": "Grid breakpoint 2" - }, - { - "name": "grid_layout3", - "value": "Grid columns and gutter" - }, - { - "name": "grid_layout4", - "value": "Grid margin" - }, - { - "name": "grid_layout5", - "value": "Grid span" - }, - { - "name": "grid_layout6", - "value": "Grid offset" - }, - { - "name": "grid_layout7", - "value": "Grid order" - }, - { - "name": "grid_layout8", - "value": "Grid inheritance of span/offset/order" - }, - { - "name": "grid_layout9", - "value": "Grid nested" - }, - { - "name": "grid_layout10", - "value": "Grid alignItem" - }, - { - "name": "typical_scenario", - "value": "Typical scenario" - }, - { - "name": "diversion_layout", - "value": "Diversion layout" - }, - { - "name": "repeat_layout", - "value": "Repeat layout" - }, - { - "name": "indentation_layout", - "value": "Indentation layout" - }, - { - "name": "header", - "value": "header" - }, - { - "name": "banner", - "value": "banner" - }, - { - "name": "operationEntries", - "value": "operation entries" - }, - { - "name": "tabs", - "value": "tabs layout" - }, - { - "name": "bigImage", - "value": "big image" - }, - { - "name": "multiLaneList", - "value": "multi lane list" - }, - { - "name": "grid", - "value": "grid layout" - }, - { - "name": "aside", - "value": "aside" - }, - { - "name": "user_improvement", - "value": "User Experience Improvement Program" - }, - { - "name": "user_improvement_tips", - "value": "The User Experience Improvement Program improves huawei's product and service quality through system, application analysis, and fault diagnosis." - }, - { - "name": "show_app_name", - "value": "App name" - }, - { - "name": "left", - "value": "Left" - }, - { - "name": "center", - "value": "Center" - }, - { - "name": "right", - "value": "Right" - }, - { - "name": "portrait", - "value": "Portrait" - }, - { - "name": "landscape", - "value": "Landscape" - }, - { - "name": "recommended", - "value": "Recommended" - }, - { - "name": "operation1", - "value": "Private FM" - }, - { - "name": "operation2", - "value": "Singer" - }, - { - "name": "operation3", - "value": "Playlist" - }, - { - "name": "operation4", - "value": "Ranking List" - }, - { - "name": "operation5", - "value": "Hot" - }, - { - "name": "operation6", - "value": "Sports Music" - }, - { - "name": "operation7", - "value": "Music FM" - }, - { - "name": "operation8", - "value": "Welfare" - }, - { - "name": "playlist_collection", - "value": "Playlist Collection" - }, - { - "name": "tabBar1", - "value": "Home" - }, - { - "name": "tabBar2", - "value": "Ranking List" - }, - { - "name": "tabBar3", - "value": "My" - }, - { - "name": "breakpoint", - "value": "breakpoint" - }, - { - "name": "Radio_GridRow_All_LCR", - "value": "All GridColl L-C-R" - }, - { - "name": "Radio_GridRow_All_TMB", - "value": "All GridColl T-M-B" - }, - { - "name": "Radio_GridRow_Sg_LCR", - "value": "Second GridCol L-C-R" - }, - { - "name": "Radio_GridRow_Sg_TMB", - "value": "Second GridCol T-M-B" - }, - { - "name": "multiScene_tabs_app", - "value": "apps" - }, - { - "name": "multiScene_tabs_play", - "value": "play" - }, - { - "name": "multiScene_tabs_me", - "value": "me" - } - ] -} \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/ohosTest/resources/zh/element/string.json b/AdaptiveCapabilities/entry/src/ohosTest/resources/zh/element/string.json deleted file mode 100644 index 2e2d24d2f2b0f10fcfd5792d263ff526199452fa..0000000000000000000000000000000000000000 --- a/AdaptiveCapabilities/entry/src/ohosTest/resources/zh/element/string.json +++ /dev/null @@ -1,300 +0,0 @@ -{ - "string": [ - { - "name": "entry_desc", - "value": "description" - }, - { - "name": "MainAbility_desc", - "value": "description" - }, - { - "name": "MainAbility_label", - "value": "eTSAdaptiveCapabilities" - }, - { - "name": "module_test_desc", - "value": "test ability description" - }, - { - "name": "TestAbility_desc", - "value": "the test ability" - }, - { - "name": "TestAbility_label", - "value": "test label" - }, - { - "name": "my_string", - "value": "手机" - }, - { - "name": "home_title", - "value": "页面开发一多能力" - }, - { - "name": "resource_qualifier", - "value": "资源文件使用" - }, - { - "name": "atomic_capability", - "value": "自适应布局" - }, - { - "name": "responsive_layout", - "value": "响应式布局" - }, - { - "name": "flex_capability_first", - "value": "拉伸能力1" - }, - { - "name": "flex_capability_second", - "value": "拉伸能力2" - }, - { - "name": "scaling_capability", - "value": "缩放能力" - }, - { - "name": "hidden_capability", - "value": "隐藏能力" - }, - { - "name": "wrap_capability", - "value": "折行能力" - }, - { - "name": "equally_capability", - "value": "均分能力" - }, - { - "name": "percentage_capability", - "value": "占比能力" - }, - { - "name": "extension_capability_first", - "value": "延伸能力1" - }, - { - "name": "extension_capability_second", - "value": "延伸能力2" - }, - { - "name": "healthy_use_phone", - "value": "健康使用手机" - }, - { - "name": "media_query", - "value": "媒体查询" - }, - { - "name": "grid_layout", - "value": "栅格布局" - }, - { - "name": "grid_layout1", - "value": "栅格断点1" - }, - { - "name": "grid_layout2", - "value": "栅格断点2" - }, - { - "name": "grid_layout3", - "value": "栅格columns和gutter" - }, - { - "name": "grid_layout4", - "value": "栅格margin" - }, - { - "name": "grid_layout5", - "value": "栅格span" - }, - { - "name": "grid_layout6", - "value": "栅格offset" - }, - { - "name": "grid_layout7", - "value": "栅格order" - }, - { - "name": "grid_layout8", - "value": "栅格span/offset/order继承性" - }, - { - "name": "grid_layout9", - "value": "栅格嵌套" - }, - { - "name": "grid_layout10", - "value": "栅格对齐" - }, - { - "name": "typical_scenario", - "value": "典型布局场景" - }, - { - "name": "diversion_layout", - "value": "挪移布局" - }, - { - "name": "repeat_layout", - "value": "重复布局" - }, - { - "name": "indentation_layout", - "value": "缩进布局" - }, - { - "name": "header", - "value": "顶部布局" - }, - { - "name": "banner", - "value": "广告栏" - }, - { - "name": "operationEntries", - "value": "操作入口" - }, - { - "name": "tabs", - "value": "页签布局" - }, - { - "name": "bigImage", - "value": "大图浏览" - }, - { - "name": "multiLaneList", - "value": "多列列表" - }, - { - "name": "grid", - "value": "网格视图" - }, - { - "name": "aside", - "value": "侧边栏" - }, - { - "name": "user_improvement", - "value": "用户体验改进计划" - }, - { - "name": "user_improvement_tips", - "value": "用户体验改进计划通过系统、应用分析、故障诊断、提升华为的产品和服务质量。" - }, - { - "name": "show_app_name", - "value": "应用名称" - }, - { - "name": "left", - "value": "左" - }, - { - "name": "center", - "value": "中" - }, - { - "name": "right", - "value": "右" - }, - { - "name": "portrait", - "value": "竖屏" - }, - { - "name": "landscape", - "value": "横屏" - }, - { - "name": "recommended", - "value": "推荐" - }, - { - "name": "operation1", - "value": "私人FM" - }, - { - "name": "operation2", - "value": "歌手" - }, - { - "name": "operation3", - "value": "歌单" - }, - { - "name": "operation4", - "value": "排行榜" - }, - { - "name": "operation5", - "value": "热门" - }, - { - "name": "operation6", - "value": "运动音乐" - }, - { - "name": "operation7", - "value": "音乐FM" - }, - { - "name": "operation8", - "value": "福利" - }, - { - "name": "playlist_collection", - "value": "歌单集合" - }, - { - "name": "tabBar1", - "value": "首页" - }, - { - "name": "tabBar2", - "value": "排行榜" - }, - { - "name": "tabBar3", - "value": "我的" - }, - { - "name": "breakpoint", - "value": "断点" - }, - { - "name": "Radio_GridRow_All_LCR", - "value": "All GridColl 左中右" - }, - { - "name": "Radio_GridRow_All_TMB", - "value": "All GridColl 上中下" - }, - { - "name": "Radio_GridRow_Sg_LCR", - "value": "Second Grid 左中右" - }, - { - "name": "Radio_GridRow_Sg_TMB", - "value": "Second Grid 上中下" - }, - { - "name": "multiScene_tabs_app", - "value": "应用" - }, - { - "name": "multiScene_tabs_play", - "value": "播放" - }, - { - "name": "multiScene_tabs_me", - "value": "我的" - } - ] -} \ No newline at end of file diff --git a/AdaptiveCapabilities/ohosTest.md b/AdaptiveCapabilities/ohosTest.md deleted file mode 100644 index b4d98716442649367ce7df1583400aff85a6bd5b..0000000000000000000000000000000000000000 --- a/AdaptiveCapabilities/ohosTest.md +++ /dev/null @@ -1,33 +0,0 @@ -|测试功能|预置条件|输入|预期输出|是否自动|测试结果| -|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------|--------------------------------| -|拉起应用| 设备正常运行| 进入首页|首页展示了自适应布局、响应式布局、典型布局场景和资源限定词四个按钮|是|Pass| -|自适应布局页面测试| 自适应布局页| 点击自适应布局按钮| 分别展示拉伸能力、缩放能力、隐藏能力、折行能力、均分能力、占比能力和延伸能力共7种自适应布局能力| 是 |Pass| -|拉伸能力1测试| 自适应布局页 | 点击拉伸能力1 | 展示拉伸能力1效果 | 是 |Pass| -|拉伸能力2测试| 自适应布局页 | 点击拉伸能力2 | 展示拉伸能力2效果 | 是 |Pass| -|缩放能力测试| 自适应布局页 | 点击缩放能力 | 展示缩放能力效果 | 是 |Pass| -|隐藏能力测试| 自适应布局页 | 点击隐藏能力 | 展示隐藏能力效果 | 是 |Pass| -|折行能力测试| 自适应布局页 | 点击折行能力 | 展示折行能力效果 | 是 |Pass| -|均分能力测试| 自适应布局页 | 点击均分能力 | 展示均分能力效果 | 是 |Pass| -|占比能力测试| 自适应布局页 | 点击占比能力 | 展示占比能力效果 | 是 |Pass| -|延伸能力1测试| 自适应布局页 | 点击延伸能力1 | 展示延伸能力1效果 | 是 |Pass| -|延伸能力2测试| 自适应布局页 | 点击延伸能力2 | 展示延伸能力2效果 | 是 |Pass| -|响应式布局页面测试| 响应式布局页| 点击响应式布局按钮| 分别展示断点、媒体查询和栅格布局3种响应式布局能力| 是 |Pass| -|断点测试| 响应式布局页 | 点击断点 | 展示断点效果 | 是 |Pass| -|媒体查询测试| 响应式布局页 | 点击媒体查询 | 展示媒体查询效果 | 是 |Pass| -|栅格布局页面测试| 栅格布局页| 点击栅格布局按钮| 分别展示栅格断点1,栅格断点2,栅格columns和gutter,栅格margin,栅格span,栅格offset,栅格order,栅格span/offset/order继承性,栅格嵌套和栅格对齐布局能力| 是 |Pass| -|典型布局场景页面测试| 典型布局场景页| 点击典型布局场景按钮| 展示了如何通过自适应布局能力和响应式布局能力,实现应用开发中的典型场景| 是 |Pass| -|挪移布局测试| 典型布局场景页 | 点击挪移布局 | 展示挪移布局效果 | 是 |Pass| -|挪移布局测试| 典型布局场景页 | 点击挪移布局 | 展示挪移布局效果 | 是 |Pass| -|挪移布局测试| 典型布局场景页 | 点击挪移布局 | 展示挪移布局效果 | 是 |Pass| -|重复布局测试| 典型布局场景页 | 点击重复布局 | 展示重复布局效果 | 是 |Pass| -|缩进布局测试| 典型布局场景页 | 点击缩进布局 | 展示缩进布局效果 | 是 |Pass| -|操作入口测试| 典型布局场景页 | 点击操作入口 | 展示操作入口效果 | 是 |Pass| -|页签布局测试| 典型布局场景页 | 点击页签布局 | 展示页签布局效果 | 是 |Pass| -|大图浏览测试| 典型布局场景页 | 点击大图浏览 | 展示大图浏览效果 | 是 |Pass| -|网格视图测试| 典型布局场景页 | 点击网格视图 | 展示网格视图效果 | 是 |Pass| -|侧边栏测试| 典型布局场景页 | 点击侧边栏 | 展示侧边栏效果 | 是 |Pass| -|一多典型场景测试| 典型布局场景页 | 点击一多典型场景 | 展示一多典型场景效果 | 是 |Pass| -|资源文件使用页面测试| 资源文件使用页| 点击资源文件使用按钮| 展示资源文件使用能力| 是 |Pass| -|一多典型场景下窗口化下自适应测试| 一多典型场景页面 | 进入应用浮窗模式,调节窗口高宽 | 展示依据窗口大小发生list数量显示的变化,ist内容文字数量变化,应用依据窗口宽度,每行数量可从2个到4个的变化,播放按钮依据窗口宽度按键的隐藏效果 | 否 |Pass| -|一多典型场景下横屏情况下自适应测试| 一多典型场景页面 | 点击首页、应用、播放 | 展示依据横屏发生tab切换为左右模式,首页分为左右分布,左边为swiper,右边为list,应用行数适配横屏,播放适配横屏 | 否 |Pass| -|交互归一能力页面测试| 交互归一能力页面 | 接入外设键盘,按上下左右导航键、空格键、ESC键、Alt键+左导航键、菜单键、上下翻页键、Ctrl键+小键盘’+’、Ctrl键+小键盘’-’ | 展示依据输入的按键信息显示对应的意图操作 | 否 |Pass| diff --git a/Weather/AppScope/app.json5 b/Weather/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a1af04785167d40b7161583a0941876ee20da3f3 --- /dev/null +++ b/Weather/AppScope/app.json5 @@ -0,0 +1,10 @@ +{ + "app": { + "bundleName": "com.example.weather", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/Weather/AppScope/resources/base/element/string.json b/Weather/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1f77ade50e483e6c4fd723695315a62909c34ef0 --- /dev/null +++ b/Weather/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "Weather" + } + ] +} diff --git a/Weather/AppScope/resources/base/media/background.png b/Weather/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/Weather/AppScope/resources/base/media/background.png differ diff --git a/Weather/AppScope/resources/base/media/foreground.png b/Weather/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/Weather/AppScope/resources/base/media/foreground.png differ diff --git a/Weather/AppScope/resources/base/media/layered_image.json b/Weather/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/Weather/AppScope/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/Weather/README.en.md b/Weather/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..9b204aff71ef062a4bbf4853781c2ad8d8081079 --- /dev/null +++ b/Weather/README.en.md @@ -0,0 +1,49 @@ +# Weather + +### Introduction + +This sample demonstrates one-time development for multi-device deployment by showing how to develop a weather app and deploy it across different devices. The demo app includes the following: home page, **Manage City** page, **Add City** page, and **Update Time** page. + +**How to Implement** + +1. Use the grid breakpoint system of responsive layout to implement different display effects on windows of different sizes. + +2. Use [SideBarContainer](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis-arkui/arkui-ts/ts-container-sidebarcontainer.md) to implement the sidebar. + +3. Use [GridRow](https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/apis-arkui/arkui-ts/ts-container-gridrow.md) to implement content split and display. + +4. Use **Canvas** and **CanvasRenderingContext2D** to draw curves that show the air quality and sunrise and sunset. + +**How to Use** + +1. After the demo app is started, weather information of the added cities is displayed on the home page. By default, two cities are present. You can swipe left or right to switch between them. The sidebar is displayed by default on a large-screen (LG) device. When the sidebar is displayed, the content area occupies 2/3 of the screen; when the sidebar is hidden, the content area automatically extends to full screen. + +2. On a device that supports free window dragging, you can drag the window to the maximum width to show the sidebar. In this case, you can tap the sidebar control button to hide or display the sidebar. If you resize the window to MD through dragging, the sidebar and sidebar control buttons will be hidden. + +3. On a device that supports window dragging, the weather content area is automatically adapted to the window size while you're dragging the window. + +4. Touch the menu button in the upper right corner and tap **Update Time**. The **Update Time** page is displayed. This page has two columns on a tablet and one column on a small-screen device. + +5. Touch the menu button in the upper right corner and tap **Manage Cities**. The **Manage Cities** page is displayed, showing the cities you've added. This page has two columns on a tablet and one column on a small-screen device like phone. + +6. Touch **Add City** on the **Manage Cities** page. On the **Add City** page displayed, tap any city that has not been added before. The city will be added to the city list and the **Manage Cities** page will be displayed. + +Display Effect + +![home](./screenshots/devices/zh/home.png) + +### Required Permissions + +N/A + +### Dependency + +N/A + +### Constraints + +1. This sample can only be run on standard-system devices. + +2. This sample demonstrates the stage model, which supports only the SDK of API version 9 (SDK version: 3.2.11.9 Beta2). + +3. DevEco Studio 3.1 Canary1 (Build Version: 3.1.0.400)must be used. diff --git a/Weather/README.md b/Weather/README.md new file mode 100644 index 0000000000000000000000000000000000000000..42dd2588bca8d66809f62fcdd2351799df504049 --- /dev/null +++ b/Weather/README.md @@ -0,0 +1,106 @@ +# 一多天气 + +### 介绍 + +本示例展示一个天气应用界面,包括首页、城市管理、添加城市、更新时间弹窗,体现一次开发,多端部署的能力。 + +1.本示例参考[一次开发,多端部署](https://gitee.com/openharmony/docs/tree/master/zh-cn/application-dev/key-features/multi-device-app-dev)的指导,主要使用响应式布局的栅格断点系统实现在不同尺寸窗口界面上不同的显示效果。 + +2.使用[SideBarContainer](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-container-sidebarcontainer.md)实现侧边栏功能。 + +3.使用[栅格容器组件](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis-arkui/arkui-ts/ts-container-gridrow.md)实现界面内容的分割和展示。 + +4.使用Canvas和CanvasRenderingContext2D完成空气质量和日出月落图的曲线绘制。 + + +### 效果预览 + +| 首页 | +|--------------------------------------| +|![home](./screenshots/devices/zh/home.png)| + +使用说明: + +1.启动应用后,首页展示已添加城市的天气信息,默认展示2个城市,左右滑动可以切换城市,在LG设备上,默认显示侧边栏,侧边栏显示时,右侧内容区占2/3,侧边栏隐藏时,内容区自动铺满界面。 + +2.在支持窗口自由拖拽的设备上,拖拽窗口大小,可以分别实现拖动到最大窗口侧边栏显示(点击侧边栏控制按钮可以隐藏和显示侧边栏),拖动窗口缩小到MD大小时侧边栏和侧边栏控制按钮隐藏。 + +3.在支持窗口自由拖拽的设备上,拖拽窗口大小,天气内容区跟随窗口大小会自动换行显示。 + +4.点击右上角菜单按钮,在菜单中点击**更新时间**,弹出更新时间弹窗,没有功能,此处只做展示,在平板设备上显示2列,在小屏设备上显示一列。 + +5.点击右上角菜单按钮,在菜单中点击**管理城市**,进入管理城市界面,展示已添加的城市,在平板设备上显示2列,在小屏设备上显示一列。 + +6.点击管理城市界面的**添加城市**,进入添加城市界面,已添加的城市不可点击,未添加的城市点击可以添加并返回管理城市界面显示。 + +### 工程目录 +``` +/code/SuperFeature/MultiDeviceAppDev/Weather/product/default +└─src + ├─main + │ │ + │ ├─ets + │ │ ├─Application + │ │ │ MyAbilityStage.ts //自定义ability + │ │ │ + │ │ ├─common //公共资源库 + │ │ ├─feature + │ │ │ AirQualityFeature.ts //空气绘画 + │ │ │ SunCanvasFeature.ts //晴天绘画 + │ │ │ + │ │ ├─MainAbility + │ │ │ MainAbility.ts //主窗口 + │ │ │ + │ │ └─pages + │ │ │ AddCity.ets //添加城市 + │ │ │ CityList.ets //城市列表 + │ │ │ Home.ets //入口 + │ │ │ + │ │ └─home + │ │ AirQuality.ets //空气质量 + │ │ HomeContent.ets //主页面 + │ │ HoursWeather.ets //每小时天气组件 + │ │ IndexEnd.ets //首页尾 + │ │ IndexHeader.ets //首页头 + │ │ IndexTitleBar.ets //首页标题 + │ │ LifeIndex.ets //生活建议 + │ │ MultidayWeather.ets //天气组件 + │ │ SideContent.ets //侧边栏 + │ │ SunCanvas.ets //晴天样式 + │ │ UpdateTimeDialog.ets //时间更新弹窗 + │ │ + │ └─resources //资源包 +``` + +### 具体实现 +1、home.ets中引入SideContent()和homeContent()。 +2、定义showSideBar来判断是否展示侧边栏,定义mediaquery.MediaQueryListener媒体监听器smListener、mdListener、lgListener。 +3、在aboutToAppear调用mediaquery对界面进行监听,[源码参考](product/default/src/main/ets/pages/Home.ets )。 +4、监听到当前屏幕大小,调用this.isBreakpoint断点,对curBp、showSideBar进行赋值,[源码参考](product/default/src/main/ets/pages/Home.ets )。 + +### 相关权限 + +不涉及。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1.本示例仅支持标准系统上运行。 + +2.本示例已适配API version 9版本SDK,版本号:3.2.11.9。 + +3.本示例需要使用DevEco Studio 3.1 Beta2 (Build Version: 3.1.0.400, built on April 7, 2023)及以上版本才可编译运行。 + +### 下载 + +如需单独下载本工程,执行如下命令: +``` +git init +git config core.sparsecheckout true +echo code/SuperFeature/MultiDeviceAppDev/Weather/ > .git/info/sparse-checkout +git remote add origin https://gitee.com/openharmony/applications_app_samples.git +git pull origin master +``` \ No newline at end of file diff --git a/Weather/build-profile.json5 b/Weather/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..7b2837f57b3b5bcd74360b2c7137b85c09ee8ddd --- /dev/null +++ b/Weather/build-profile.json5 @@ -0,0 +1,46 @@ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "targetSdkVersion": "5.1.1(19)", + "compatibleSdkVersion": "5.0.1(13)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "default", + "srcPath": "./product/default", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + }, + { + "name": "common", + "srcPath": "./common" + } + ] +} \ No newline at end of file diff --git a/Weather/code-linter.json5 b/Weather/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..073990fa45394e1f8e85d85418ee60a8953f9b99 --- /dev/null +++ b/Weather/code-linter.json5 @@ -0,0 +1,32 @@ +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/Weather/common/BuildProfile.ets b/Weather/common/BuildProfile.ets new file mode 100644 index 0000000000000000000000000000000000000000..3a501e5ddee8ea6d28961648fc7dd314a5304bd4 --- /dev/null +++ b/Weather/common/BuildProfile.ets @@ -0,0 +1,17 @@ +/** + * Use these variables when you tailor your ArkTS code. They must be of the const type. + */ +export const HAR_VERSION = '1.0.0'; +export const BUILD_MODE_NAME = 'debug'; +export const DEBUG = true; +export const TARGET_NAME = 'default'; + +/** + * BuildProfile Class is used only for compatibility purposes. + */ +export default class BuildProfile { + static readonly HAR_VERSION = HAR_VERSION; + static readonly BUILD_MODE_NAME = BUILD_MODE_NAME; + static readonly DEBUG = DEBUG; + static readonly TARGET_NAME = TARGET_NAME; +} \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/main/ets/Application/AbilityStage.ts b/Weather/common/Index.ets similarity index 45% rename from AdaptiveCapabilities/entry/src/main/ets/Application/AbilityStage.ts rename to Weather/common/Index.ets index ad77c5745710202982d8f742a721ee67a3089be7..7eb2ed98ecd8aad383a3d8501948f32d22623162 100644 --- a/AdaptiveCapabilities/entry/src/main/ets/Application/AbilityStage.ts +++ b/Weather/common/Index.ets @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 @@ -13,11 +13,36 @@ * limitations under the License. */ -import AbilityStage from '@ohos.app.ability.AbilityStage' -import Logger from '../model/Logger' +export { + getUpdateTimes, + getMenuInfo, + getHeaderDate, + getCityList, + addCity, + getCityListWeatherData, + getHoursData, + getWeekWeatherData, + getAirIndexData, + getLifeData, + getSideBg, + getBg +} from './src/main/ets/mock/RequestData'; -export default class MyAbilityStage extends AbilityStage { - onCreate() { - Logger.info('[Sample_AdaptiveCapabilities]', 'MyAbilityStage onCreate') - } -} \ No newline at end of file +export { MyDataSource } from './src/main/ets/model/BasicDataSource'; + +export { + HeaderData, + CityListData, + Forecast, + AirIndex, + SuitData, + WeekWeather, + AirData, + City +} from './src/main/ets/model/Main'; + +export { Logger } from './src/main/ets/util/Logger'; + +export { Style } from './src/main/ets/util/Style'; + +export { MenuData } from './src/main/ets/model/MenuData'; \ No newline at end of file diff --git a/Weather/common/build-profile.json5 b/Weather/common/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e6773f9f5d76a66d6d19fddc9c6ddb3f5621d3b1 --- /dev/null +++ b/Weather/common/build-profile.json5 @@ -0,0 +1,31 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + }, + "consumerFiles": [ + "./consumer-rules.txt" + ] + } + }, + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest" + } + ] +} diff --git a/Weather/common/consumer-rules.txt b/Weather/common/consumer-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Weather/common/hvigorfile.ts b/Weather/common/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..805c5d7f6809c51cff0b4adcc1142979f8f864b6 --- /dev/null +++ b/Weather/common/hvigorfile.ts @@ -0,0 +1,6 @@ +import { harTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/Weather/common/obfuscation-rules.txt b/Weather/common/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/Weather/common/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/Weather/common/oh-package.json5 b/Weather/common/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..538a06bede356ebbbd0036c7645f9bd920d11bff --- /dev/null +++ b/Weather/common/oh-package.json5 @@ -0,0 +1,9 @@ +{ + "name": "common", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "Index.ets", + "author": "", + "license": "Apache-2.0", + "dependencies": {} +} diff --git a/Weather/common/src/main/ets/mock/CityInfo.ets b/Weather/common/src/main/ets/mock/CityInfo.ets new file mode 100644 index 0000000000000000000000000000000000000000..1e5d86d9c9055b3f02cf0825549107c4783ed522 --- /dev/null +++ b/Weather/common/src/main/ets/mock/CityInfo.ets @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2025 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. + */ + +export const cityData: CityInfo[] = [ + { + "name": "北京", + "temp": "32", + "weather": "晴" + }, + { + "name": "上海", + "temp": "28", + "weather": "阴" + }, + { + "name": "广州", + "temp": "35", + "weather": "小雨" + }, + { + "name": "天津", + "temp": "35", + "weather": "中雨" + }, + { + "name": "武汉", + "temp": "26", + "weather": "多云" + }, + { + "name": "沈阳", + "temp": "25", + "weather": "晴" + }, + { + "name": "重庆", + "temp": "27", + "weather": "小雨" + }, + { + "name": "杭州", + "temp": "35", + "weather": "晴" + }, + { + "name": "南京", + "temp": "25", + "weather": "晴" + }, + { + "name": "哈尔滨", + "temp": "25", + "weather": "晴" + }, + { + "name": "长春", + "temp": "28", + "weather": "阵雨" + }, + { + "name": "呼和浩特", + "temp": "25", + "weather": "晴" + }, + { + "name": "石家庄", + "temp": "25", + "weather": "晴" + }, + { + "name": "银川", + "temp": "25", + "weather": "晴" + }, + { + "name": "乌鲁木齐", + "temp": "25", + "weather": "晴" + }, + { + "name": "拉萨", + "temp": "35", + "weather": "晴" + }, + { + "name": "西宁", + "temp": "25", + "weather": "晴" + }, + { + "name": "西安", + "temp": "25", + "weather": "晴" + }, + { + "name": "兰州", + "temp": "25", + "weather": "多云" + }, + { + "name": "太原", + "temp": "25", + "weather": "阴" + }, + { + "name": "昆明", + "temp": "25", + "weather": "小雨" + }, + { + "name": "南宁", + "temp": "20", + "weather": "晴" + } +]; + +export class CityInfo { + name: string = ''; + temp: string = ''; + weather: string = ''; +} \ No newline at end of file diff --git a/Weather/common/src/main/ets/mock/Mock.ets b/Weather/common/src/main/ets/mock/Mock.ets new file mode 100644 index 0000000000000000000000000000000000000000..443d7986806058efe74872278bef40338c92b6eb --- /dev/null +++ b/Weather/common/src/main/ets/mock/Mock.ets @@ -0,0 +1,2926 @@ +/* + * Copyright (c) 2025 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. + */ + +export const weather: CityFull[] = [ + { + "cityId": "101210101", + "city": "北京", + "cityEn": "beijing", + "country": "中国", + "countryEn": "China", + "updateTime": "2022-06-23 13:09:59", + "data": [ + { + "day": "23日(星期四)", + "date": "2022-06-23", + "week": "星期四", + "wea": "阴", + "weaImg": "yun", + "weaDay": "阴", + "weaDayImg": "yun", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "32", + "tem1": "35", + "tem2": "25", + "humidity": "40%", + "visibility": "24km", + "pressure": "998", + "win": [ + "西南风", + "西南风" + ], + "winSpeed": "5-6级转3-4级", + "winMeter": "18km/h", + "sunrise": "04:58", + "sunset": "19:04", + "air": "20", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "24日(星期五)", + "date": "2022-06-24", + "week": "星期五", + "wea": "晴", + "weaImg": "yu", + "weaDay": "晴", + "weaDayImg": "yu", + "weaNight": "晴", + "weaNightImg": "yu", + "tem": "32", + "tem1": "35", + "tem2": "25", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "西南风", + "西南风" + ], + "winSpeed": "3-4级", + "winMeter": "", + "sunrise": "04:58", + "sunset": "19:04", + "air": "20", + "airLevel": "优", + "airTips": "当前晴,炎热,不适合外出游玩!", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [ + { + "hours": "09时", + "wea": "晴", + "weaImg": "sunny", + "tem": "30", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "10时", + "wea": "晴", + "weaImg": "sunny", + "tem": "30", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "11时", + "wea": "多云", + "weaImg": "sunny", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "12时", + "wea": "晴", + "weaImg": "sunny", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "13时", + "wea": "晴", + "weaImg": "sunny", + "tem": "32", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "14时", + "wea": "晴", + "weaImg": "sunny", + "tem": "32", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "15时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "16时", + "wea": "晴", + "weaImg": "sunny", + "tem": "30", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "17时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "30", + "win": "西北风", + "winSpeed": "3-4级" + }, + { + "hours": "18时", + "wea": "晴", + "weaImg": "sunny", + "tem": "29", + "win": "西风", + "winSpeed": "<3级" + }, + { + "hours": "19时", + "wea": "晴", + "weaImg": "sunny", + "tem": "28", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "20时", + "wea": "晴", + "weaImg": "sunny", + "tem": "28", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "21时", + "wea": "晴", + "weaImg": "sunny", + "tem": "27", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "22时", + "wea": "晴", + "weaImg": "sunny", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "23时", + "wea": "晴", + "weaImg": "sunny", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "00时", + "wea": "晴", + "weaImg": "sunny", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "01时", + "wea": "晴", + "weaImg": "sunny", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "02时", + "wea": "晴", + "weaImg": "sunny", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "03时", + "wea": "多云", + "weaImg": "sunny", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "04时", + "wea": "晴", + "weaImg": "sunny", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "05时", + "wea": "晴", + "weaImg": "sunny", + "tem": "25", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "06时", + "wea": "晴", + "weaImg": "sunny", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "07时", + "wea": "晴", + "weaImg": "sunny", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "08时", + "wea": "晴", + "weaImg": "sunny", + "tem": "29", + "win": "西南风", + "winSpeed": "3-4级" + }, + ], + "index": [ + { + "title": "湿度", + "level": "42%", + "desc": "湿度刚好。" + }, + { + "title": "体感温度", + "level": "28°", + "desc": "" + }, + { + "title": "风力", + "level": "微风", + "desc": "风力较弱,适宜户外活动。" + }, + { + "title": "风向", + "level": "北风", + "desc": "" + }, + { + "title": "穿衣", + "level": "短袖", + "desc": "建议穿短衫、短裤等清凉夏季服装。" + }, + { + "title": "运动", + "level": "宜室内", + "desc": "" + }, + { + "title": "感冒", + "level": "容易", + "desc": "昼夜温差大,注意预防感冒。" + }, + { + "title": "紫外线", + "level": "强", + "desc": "辐射强,涂擦SPF8-12防晒护肤品。" + } + ] + }, + { + "day": "25日(星期六)", + "date": "2022-06-25", + "week": "星期六", + "wea": "多云", + "weaImg": "cloudy", + "weaDay": "多云", + "weaDayImg": "yun", + "weaNight": "多云", + "weaNightImg": "yun", + "tem": "34", + "tem1": "32", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "无持续风向" + ], + "winSpeed": "4-5级转<3级", + "winMeter": "", + "sunrise": "04:58", + "sunset": "19:04", + "air": "34", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "26日(星期日)", + "date": "2022-06-26", + "week": "星期日", + "wea": "小雨", + "weaImg": "yin", + "weaDay": "小雨", + "weaDayImg": "yin", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "36", + "tem1": "36", + "tem2": "27", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "南风" + ], + "winSpeed": "4-5级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "29", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "27日(星期一)", + "date": "2022-06-27", + "week": "星期一", + "wea": "阴", + "weaImg": "yin", + "weaDay": "阴", + "weaDayImg": "yin", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "36", + "tem1": "36", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "南风" + ], + "winSpeed": "4-5级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "26", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "28日(星期二)", + "date": "2022-06-28", + "week": "星期二", + "wea": "晴", + "weaImg": "sunny", + "weaDay": "晴", + "weaDayImg": "sunny", + "weaNight": "晴", + "weaNightImg": "sunny", + "tem": "36", + "tem1": "36", + "tem2": "27", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "西南风", + "南风" + ], + "winSpeed": "4-5级转3-4级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "38", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "29日(星期三)", + "date": "2022-06-29", + "week": "星期三", + "wea": "多云", + "weaImg": "cloudy", + "weaDay": "多云", + "weaDayImg": "cloudy", + "weaNight": "多云", + "weaNightImg": "cloudy", + "tem": "35", + "tem1": "35", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "无持续风向", + "无持续风向" + ], + "winSpeed": "<3级", + "winMeter": "", + "sunrise": "05:00", + "sunset": "19:04", + "air": "31", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + } + ], + "aqi": { + "updateTime": "13:44", + "cityId": "101210101", + "city": "北京", + "cityEn": "hangzhou", + "country": "中国", + "countryEn": "China", + "air": "28", + "airLevel": "优", + "airTips": "空气很好,可以外出活动,呼吸新鲜空气,拥抱大自然!", + "pm25": "94", + "pm25Desc": "优", + "pm10": "181", + "pm10Desc": "优", + "o3": "19", + "o3Desc": "优", + "no2": "105", + "no2Desc": "优", + "so2": "67", + "so2Desc": "优", + "co": "19", + "coDesc": "-", + "kouzhao": "不用佩戴口罩", + "yundong": "非常适宜运动", + "waichu": "适宜外出", + "kaichuang": "适宜开窗", + "jinghuaqi": "关闭净化器" + } + }, + { + "cityId": "101210102", + "city": "上海", + "cityEn": "shanghai", + "country": "中国", + "countryEn": "China", + "updateTime": "2022-06-23 13:09:59", + "data": [ + { + "day": "23日(星期四)", + "date": "2022-06-23", + "week": "星期四", + "wea": "多云", + "weaImg": "yun", + "weaDay": "多云", + "weaDayImg": "cloudy", + "weaNight": "多云", + "weaNightImg": "cloudy", + "tem": "28", + "tem1": "36", + "tem2": "28", + "humidity": "40%", + "visibility": "24km", + "pressure": "998", + "win": [ + "西南风", + "西南风" + ], + "winSpeed": "5-6级转3-4级", + "winMeter": "18km/h", + "sunrise": "04:58", + "sunset": "19:04", + "air": "20", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "24日(星期五)", + "date": "2022-06-24", + "week": "星期五", + "wea": "阴", + "weaImg": "yin", + "weaDay": "阴", + "weaDayImg": "yin", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "28", + "tem1": "32", + "tem2": "25", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "西南风", + "西南风" + ], + "winSpeed": "3-4级", + "winMeter": "", + "sunrise": "04:58", + "sunset": "19:04", + "air": "32", + "airLevel": "优", + "airTips": "当前阴,紫外线弱,适合外出游玩!", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [ + { + "hours": "08时", + "wea": "阴", + "weaImg": "yin", + "tem": "29", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "09时", + "wea": "阴", + "weaImg": "yu", + "tem": "30", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "10时", + "wea": "小雨", + "weaImg": "yu", + "tem": "30", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "11时", + "wea": "阴", + "weaImg": "yu", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "12时", + "wea": "多云", + "weaImg": "yu", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "13时", + "wea": "阴", + "weaImg": "yu", + "tem": "32", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "14时", + "wea": "阴", + "weaImg": "yu", + "tem": "32", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "15时", + "wea": "阴", + "weaImg": "yu", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "16时", + "wea": "阴", + "weaImg": "yu", + "tem": "30", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "17时", + "wea": "阴", + "weaImg": "yu", + "tem": "30", + "win": "西北风", + "winSpeed": "3-4级" + }, + { + "hours": "18时", + "wea": "阴", + "weaImg": "yu", + "tem": "29", + "win": "西风", + "winSpeed": "<3级" + }, + { + "hours": "19时", + "wea": "阴", + "weaImg": "yu", + "tem": "28", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "20时", + "wea": "多云", + "weaImg": "yu", + "tem": "28", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "21时", + "wea": "阴", + "weaImg": "yu", + "tem": "27", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "22时", + "wea": "阴", + "weaImg": "yu", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "23时", + "wea": "阴", + "weaImg": "yu", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "00时", + "wea": "阴", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "01时", + "wea": "小雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "02时", + "wea": "阴", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "03时", + "wea": "阴", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "04时", + "wea": "阴", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "05时", + "wea": "阴", + "weaImg": "yu", + "tem": "25", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "06时", + "wea": "阴", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "07时", + "wea": "多云", + "weaImg": "yu", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + } + ], + "index": [ + { + "title": "湿度", + "level": "45%", + "desc": "湿度刚好。" + }, + { + "title": "体感温度", + "level": "28°", + "desc": "" + }, + { + "title": "风力", + "level": "微风", + "desc": "风力较弱,适宜户外活动。" + }, + { + "title": "风向", + "level": "南风", + "desc": "" + }, + { + "title": "穿衣", + "level": "短袖", + "desc": "建议穿短衫、短裤等清凉夏季服装。" + }, + { + "title": "运动", + "level": "宜室内", + "desc": "" + }, + { + "title": "感冒", + "level": "容易", + "desc": "昼夜温差大,注意预防感冒。" + }, + { + "title": "紫外线", + "level": "弱", + "desc": "辐射弱,涂擦SPF8-12防晒护肤品。" + } + ] + }, + { + "day": "25日(星期六)", + "date": "2022-06-25", + "week": "星期六", + "wea": "多云", + "weaImg": "yun", + "weaDay": "多云", + "weaDayImg": "yun", + "weaNight": "多云", + "weaNightImg": "yun", + "tem": "34", + "tem1": "34", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "无持续风向" + ], + "winSpeed": "4-5级转<3级", + "winMeter": "", + "sunrise": "04:58", + "sunset": "19:04", + "air": "34", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "26日(星期日)", + "date": "2022-06-26", + "week": "星期日", + "wea": "阴", + "weaImg": "yin", + "weaDay": "阴", + "weaDayImg": "yin", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "36", + "tem1": "36", + "tem2": "27", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "南风" + ], + "winSpeed": "4-5级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "29", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "27日(星期一)", + "date": "2022-06-27", + "week": "星期一", + "wea": "阴", + "weaImg": "yin", + "weaDay": "阴", + "weaDayImg": "yin", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "36", + "tem1": "36", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "南风" + ], + "winSpeed": "4-5级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "26", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "28日(星期二)", + "date": "2022-06-28", + "week": "星期二", + "wea": "多云", + "weaImg": "yin", + "weaDay": "多云", + "weaDayImg": "yin", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "36", + "tem1": "36", + "tem2": "27", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "西南风", + "南风" + ], + "winSpeed": "4-5级转3-4级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "38", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "29日(星期三)", + "date": "2022-06-29", + "week": "星期三", + "wea": "小雨", + "weaImg": "yu", + "weaDay": "小雨", + "weaDayImg": "yu", + "weaNight": "小雨", + "weaNightImg": "yu", + "tem": "35", + "tem1": "35", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "无持续风向", + "无持续风向" + ], + "winSpeed": "<3级", + "winMeter": "", + "sunrise": "05:00", + "sunset": "19:04", + "air": "31", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + } + ], + "aqi": { + "updateTime": "13:44", + "cityId": "101210102", + "city": "上海", + "cityEn": "shanghai", + "country": "中国", + "countryEn": "China", + "air": "32", + "airLevel": "优", + "airTips": "空气很好,可以外出活动,呼吸新鲜空气,拥抱大自然!", + "pm25": "80", + "pm25Desc": "优", + "pm10": "200", + "pm10Desc": "优", + "o3": "39", + "o3Desc": "优", + "no2": "100", + "no2Desc": "优", + "so2": "70", + "so2Desc": "优", + "co": "20", + "coDesc": "-", + "kouzhao": "不用佩戴口罩", + "yundong": "非常适宜运动", + "waichu": "适宜外出", + "kaichuang": "适宜开窗", + "jinghuaqi": "关闭净化器" + } + }, + { + "cityId": "101210103", + "city": "广州", + "cityEn": "guangzhou", + "country": "中国", + "countryEn": "China", + "updateTime": "2022-06-23 13:09:59", + "data": [ + { + "day": "23日(星期四)", + "date": "2022-06-23", + "week": "星期四", + "wea": "小雨", + "weaImg": "rain", + "weaDay": "小雨", + "weaDayImg": "rain", + "weaNight": "小雨", + "weaNightImg": "rain", + "tem": "36", + "tem1": "38", + "tem2": "30", + "humidity": "50%", + "visibility": "24km", + "pressure": "998", + "win": [ + "西南风", + "西南风" + ], + "winSpeed": "5-6级转3-4级", + "winMeter": "18km/h", + "sunrise": "04:58", + "sunset": "19:04", + "air": "40", + "airLevel": "优", + "airTips": "当前多云,昨天和今天温度一致,适合外出游玩!", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "24日(星期五)", + "date": "2022-06-24", + "week": "星期五", + "wea": "小雨", + "weaImg": "yu", + "weaDay": "小雨", + "weaDayImg": "yu", + "weaNight": "小雨", + "weaNightImg": "yu", + "tem": "26", + "tem1": "30", + "tem2": "22", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "西南风", + "西南风" + ], + "winSpeed": "3-4级", + "winMeter": "", + "sunrise": "04:58", + "sunset": "19:04", + "air": "27", + "airLevel": "优", + "airTips": "今天小雨,天气凉爽", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [ + { + "hours": "08时", + "wea": "阴", + "weaImg": "yin", + "tem": "29", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "09时", + "wea": "小雨", + "weaImg": "yu", + "tem": "30", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "10时", + "wea": "小雨", + "weaImg": "yu", + "tem": "30", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "11时", + "wea": "小雨", + "weaImg": "yu", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "12时", + "wea": "小雨", + "weaImg": "yu", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "13时", + "wea": "小雨", + "weaImg": "yu", + "tem": "32", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "14时", + "wea": "阴", + "weaImg": "yin", + "tem": "32", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "15时", + "wea": "小雨", + "weaImg": "yu", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "16时", + "wea": "小雨", + "weaImg": "yu", + "tem": "30", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "17时", + "wea": "小雨", + "weaImg": "yu", + "tem": "30", + "win": "西北风", + "winSpeed": "3-4级" + }, + { + "hours": "18时", + "wea": "小雨", + "weaImg": "yu", + "tem": "29", + "win": "西风", + "winSpeed": "<3级" + }, + { + "hours": "19时", + "wea": "小雨", + "weaImg": "yu", + "tem": "28", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "20时", + "wea": "小雨", + "weaImg": "yu", + "tem": "28", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "21时", + "wea": "小雨", + "weaImg": "yu", + "tem": "27", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "22时", + "wea": "小雨", + "weaImg": "yu", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "23时", + "wea": "小雨", + "weaImg": "yu", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "00时", + "wea": "小雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "01时", + "wea": "小雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "02时", + "wea": "小雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "03时", + "wea": "小雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "04时", + "wea": "小雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "05时", + "wea": "小雨", + "weaImg": "yu", + "tem": "25", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "06时", + "wea": "小雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "07时", + "wea": "小雨", + "weaImg": "yu", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + } + ], + "index": [ + { + "title": "湿度", + "level": "50%", + "desc": "湿度刚好。" + }, + { + "title": "体感温度", + "level": "27°", + "desc": "" + }, + { + "title": "风力", + "level": "大风", + "desc": "风力较弱,适宜户外活动。" + }, + { + "title": "风向", + "level": "东南风", + "desc": "" + }, + { + "title": "穿衣", + "level": "长袖", + "desc": "建议穿短衫、短裤等清凉夏季服装。" + }, + { + "title": "运动", + "level": "宜室内", + "desc": "" + }, + { + "title": "感冒", + "level": "容易", + "desc": "昼夜温差大,注意预防感冒。" + }, + { + "title": "紫外线", + "level": "弱", + "desc": "辐射弱,涂擦SPF8-12防晒护肤品。" + } + ] + }, + { + "day": "25日(星期六)", + "date": "2022-06-25", + "week": "星期六", + "wea": "多云", + "weaImg": "yun", + "weaDay": "多云", + "weaDayImg": "yun", + "weaNight": "多云", + "weaNightImg": "yun", + "tem": "34", + "tem1": "34", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "无持续风向" + ], + "winSpeed": "4-5级转<3级", + "winMeter": "", + "sunrise": "04:58", + "sunset": "19:04", + "air": "34", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "26日(星期日)", + "date": "2022-06-26", + "week": "星期日", + "wea": "阴", + "weaImg": "yin", + "weaDay": "阴", + "weaDayImg": "yin", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "36", + "tem1": "36", + "tem2": "27", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "南风" + ], + "winSpeed": "4-5级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "29", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "27日(星期一)", + "date": "2022-06-27", + "week": "星期一", + "wea": "阴", + "weaImg": "yin", + "weaDay": "阴", + "weaDayImg": "yin", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "36", + "tem1": "36", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "南风" + ], + "winSpeed": "4-5级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "26", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "28日(星期二)", + "date": "2022-06-28", + "week": "星期二", + "wea": "中雨", + "weaImg": "rain", + "weaDay": "中雨", + "weaDayImg": "rain", + "weaNight": "中雨", + "weaNightImg": "rain", + "tem": "36", + "tem1": "36", + "tem2": "27", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "西南风", + "南风" + ], + "winSpeed": "4-5级转3-4级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "38", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "29日(星期三)", + "date": "2022-06-29", + "week": "星期三", + "wea": "中雨", + "weaImg": "rain", + "weaDay": "中雨", + "weaDayImg": "rain", + "weaNight": "小雨", + "weaNightImg": "yu", + "tem": "35", + "tem1": "35", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "无持续风向", + "无持续风向" + ], + "winSpeed": "<3级", + "winMeter": "", + "sunrise": "05:00", + "sunset": "19:04", + "air": "31", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + } + ], + "aqi": { + "updateTime": "13:44", + "cityId": "101210103", + "city": "广州", + "cityEn": "guangzhou", + "country": "中国", + "countryEn": "China", + "air": "50", + "airLevel": "良", + "airTips": "空气良好,湿度较高,适宜室内活动!", + "pm25": "90", + "pm25Desc": "优", + "pm10": "170", + "pm10Desc": "优", + "o3": "18", + "o3Desc": "优", + "no2": "90", + "no2Desc": "优", + "so2": "64", + "so2Desc": "优", + "co": "22", + "coDesc": "-", + "kouzhao": "不用佩戴口罩", + "yundong": "非常适宜运动", + "waichu": "适宜外出", + "kaichuang": "适宜开窗", + "jinghuaqi": "关闭净化器" + } + }, + { + "cityId": "101210104", + "city": "天津", + "cityEn": "tianjin", + "country": "中国", + "countryEn": "China", + "updateTime": "2022-06-23 13:09:59", + "data": [ + { + "day": "23日(星期四)", + "date": "2022-06-23", + "week": "星期四", + "wea": "阴", + "weaImg": "yin", + "weaDay": "阴", + "weaDayImg": "yin", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "33", + "tem1": "35", + "tem2": "22", + "humidity": "55%", + "visibility": "24km", + "pressure": "998", + "win": [ + "北风", + "北风" + ], + "winSpeed": "5-6级转3-4级", + "winMeter": "18km/h", + "sunrise": "04:58", + "sunset": "19:04", + "air": "35", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "24日(星期五)", + "date": "2022-06-24", + "week": "星期五", + "wea": "中雨", + "weaImg": "yu", + "weaDay": "中雨", + "weaDayImg": "yu", + "weaNight": "中雨", + "weaNightImg": "yu", + "tem": "32", + "tem1": "32", + "tem2": "25", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "西南风", + "西南风" + ], + "winSpeed": "4级", + "winMeter": "", + "sunrise": "04:58", + "sunset": "19:04", + "air": "30", + "airLevel": "优", + "airTips": "今天中雨,出门记得带伞哦!", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [ + { + "hours": "08时", + "wea": "阴", + "weaImg": "yin", + "tem": "29", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "09时", + "wea": "小雨", + "weaImg": "yu", + "tem": "30", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "10时", + "wea": "中雨", + "weaImg": "yu", + "tem": "30", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "11时", + "wea": "中雨", + "weaImg": "yu", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "12时", + "wea": "小雨", + "weaImg": "yu", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "13时", + "wea": "中雨", + "weaImg": "yu", + "tem": "32", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "14时", + "wea": "中雨", + "weaImg": "yu", + "tem": "32", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "15时", + "wea": "小雨", + "weaImg": "yu", + "tem": "31", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "16时", + "wea": "中雨", + "weaImg": "yu", + "tem": "30", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "17时", + "wea": "中雨", + "weaImg": "yu", + "tem": "30", + "win": "西北风", + "winSpeed": "3-4级" + }, + { + "hours": "18时", + "wea": "中雨", + "weaImg": "yu", + "tem": "29", + "win": "西风", + "winSpeed": "<3级" + }, + { + "hours": "19时", + "wea": "小雨", + "weaImg": "yu", + "tem": "28", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "20时", + "wea": "中雨", + "weaImg": "yu", + "tem": "28", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "21时", + "wea": "小雨", + "weaImg": "yu", + "tem": "27", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "22时", + "wea": "小雨", + "weaImg": "yu", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "23时", + "wea": "中雨", + "weaImg": "yu", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "00时", + "wea": "小雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "01时", + "wea": "中雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "02时", + "wea": "中雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "03时", + "wea": "中雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "04时", + "wea": "小雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "05时", + "wea": "中雨", + "weaImg": "yu", + "tem": "25", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "06时", + "wea": "小雨", + "weaImg": "yu", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "07时", + "wea": "中雨", + "weaImg": "yu", + "tem": "27", + "win": "南风", + "winSpeed": "3-4级" + } + ], + "index": [ + { + "title": "湿度", + "level": "55%", + "desc": "湿度较高。" + }, + { + "title": "体感温度", + "level": "35°", + "desc": "" + }, + { + "title": "风力", + "level": "微风", + "desc": "风力较弱,适宜户外活动。" + }, + { + "title": "风向", + "level": "南风", + "desc": "" + }, + { + "title": "穿衣", + "level": "短袖", + "desc": "建议穿短衫、短裤等清凉夏季服装。" + }, + { + "title": "运动", + "level": "宜室内", + "desc": "" + }, + { + "title": "感冒", + "level": "容易", + "desc": "昼夜温差大,注意预防感冒。" + }, + { + "title": "紫外线", + "level": "弱", + "desc": "辐射弱,涂擦SPF8-12防晒护肤品。" + } + ] + }, + { + "day": "25日(星期六)", + "date": "2022-06-25", + "week": "星期六", + "wea": "阴", + "weaImg": "yin", + "weaDay": "阴", + "weaDayImg": "yin", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "34", + "tem1": "36", + "tem2": "22", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "无持续风向" + ], + "winSpeed": "4-5级转<3级", + "winMeter": "", + "sunrise": "04:58", + "sunset": "19:04", + "air": "34", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "26日(星期日)", + "date": "2022-06-26", + "week": "星期日", + "wea": "阴", + "weaImg": "yin", + "weaDay": "阴", + "weaDayImg": "yin", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "36", + "tem1": "38", + "tem2": "27", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "南风" + ], + "winSpeed": "4-5级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "29", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "27日(星期一)", + "date": "2022-06-27", + "week": "星期一", + "wea": "多云", + "weaImg": "cloudy", + "weaDay": "多云", + "weaDayImg": "cloudy", + "weaNight": "多云", + "weaNightImg": "cloudy", + "tem": "36", + "tem1": "36", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "南风" + ], + "winSpeed": "4-5级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "26", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "28日(星期二)", + "date": "2022-06-28", + "week": "星期二", + "wea": "晴", + "weaImg": "sunny", + "weaDay": "晴", + "weaDayImg": "sunny", + "weaNight": "晴", + "weaNightImg": "sunny", + "tem": "36", + "tem1": "36", + "tem2": "27", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "西南风", + "南风" + ], + "winSpeed": "4-5级转3-4级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "38", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "29日(星期三)", + "date": "2022-06-29", + "week": "星期三", + "wea": "晴", + "weaImg": "sunny", + "weaDay": "晴", + "weaDayImg": "sunny", + "weaNight": "晴", + "weaNightImg": "sunny", + "tem": "35", + "tem1": "35", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "无持续风向", + "无持续风向" + ], + "winSpeed": "<3级", + "winMeter": "", + "sunrise": "05:00", + "sunset": "19:04", + "air": "31", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + } + ], + "aqi": { + "updateTime": "13:44", + "cityId": "101210104", + "city": "天津", + "cityEn": "tianjin", + "country": "中国", + "countryEn": "China", + "air": "50", + "airLevel": "良", + "airTips": "空气良好,可以外出活动,呼吸新鲜空气,拥抱大自然!", + "pm25": "95", + "pm25Desc": "优", + "pm10": "180", + "pm10Desc": "优", + "o3": "30", + "o3Desc": "良", + "no2": "150", + "no2Desc": "良", + "so2": "65", + "so2Desc": "优", + "co": "19", + "coDesc": "-", + "kouzhao": "不用佩戴口罩", + "yundong": "非常适宜运动", + "waichu": "适宜外出", + "kaichuang": "适宜开窗", + "jinghuaqi": "关闭净化器" + } + }, + { + "cityId": "101210105", + "city": "武汉", + "cityEn": "wuhan", + "country": "中国", + "countryEn": "China", + "updateTime": "2022-06-23 13:09:59", + "data": [ + { + "day": "23日(星期四)", + "date": "2022-06-23", + "week": "星期四", + "wea": "多云", + "weaImg": "yun", + "weaDay": "多云", + "weaDayImg": "yun", + "weaNight": "阴", + "weaNightImg": "yin", + "tem": "35", + "tem1": "39", + "tem2": "25", + "humidity": "40%", + "visibility": "24km", + "pressure": "998", + "win": [ + "西南风", + "西南风" + ], + "winSpeed": "5-6级转3-4级", + "winMeter": "18km/h", + "sunrise": "04:58", + "sunset": "19:04", + "air": "20", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [ + { + "hours": "08时", + "wea": "阴", + "weaImg": "yin", + "tem": "29", + "win": "西南风", + "winSpeed": "3级" + }, + { + "hours": "09时", + "wea": "阴", + "weaImg": "yin", + "tem": "31", + "win": "西南风", + "winSpeed": "4级" + }, + { + "hours": "10时", + "wea": "阴", + "weaImg": "yin", + "tem": "32", + "win": "西南风", + "winSpeed": "5级" + }, + { + "hours": "11时", + "wea": "多云", + "weaImg": "yun", + "tem": "34", + "win": "西南风", + "winSpeed": "5级" + }, + { + "hours": "12时", + "wea": "多云", + "weaImg": "yun", + "tem": "34", + "win": "西南风", + "winSpeed": "5级" + }, + { + "hours": "13时", + "wea": "多云", + "weaImg": "yun", + "tem": "35", + "win": "西南风", + "winSpeed": "6级" + }, + { + "hours": "14时", + "wea": "多云", + "weaImg": "yun", + "tem": "36", + "win": "西南风", + "winSpeed": "5级" + }, + { + "hours": "15时", + "wea": "多云", + "weaImg": "yun", + "tem": "35", + "win": "西南风", + "winSpeed": "6级" + }, + { + "hours": "16时", + "wea": "多云", + "weaImg": "yun", + "tem": "35", + "win": "西南风", + "winSpeed": "5级" + }, + { + "hours": "17时", + "wea": "多云", + "weaImg": "yun", + "tem": "35", + "win": "西南风", + "winSpeed": "4级" + }, + { + "hours": "18时", + "wea": "多云", + "weaImg": "yun", + "tem": "34", + "win": "西南风", + "winSpeed": "4级" + }, + { + "hours": "19时", + "wea": "多云", + "weaImg": "yun", + "tem": "32", + "win": "西南风", + "winSpeed": "4级" + }, + { + "hours": "20时", + "wea": "多云", + "weaImg": "yun", + "tem": "31", + "win": "西南风", + "winSpeed": "4级" + }, + { + "hours": "21时", + "wea": "阴", + "weaImg": "yin", + "tem": "31", + "win": "西南风", + "winSpeed": "4级" + }, + { + "hours": "22时", + "wea": "阴", + "weaImg": "yin", + "tem": "30", + "win": "西南风", + "winSpeed": "4级" + }, + { + "hours": "23时", + "wea": "阴", + "weaImg": "yin", + "tem": "29", + "win": "西南风", + "winSpeed": "3级" + }, + { + "hours": "00时", + "wea": "阴", + "weaImg": "yin", + "tem": "29", + "win": "西南风", + "winSpeed": "3级" + }, + { + "hours": "01时", + "wea": "阴", + "weaImg": "yin", + "tem": "29", + "win": "西南风", + "winSpeed": "3级" + }, + { + "hours": "02时", + "wea": "阴", + "weaImg": "yin", + "tem": "28", + "win": "西南风", + "winSpeed": "3级" + }, + { + "hours": "03时", + "wea": "阴", + "weaImg": "yin", + "tem": "28", + "win": "西南风", + "winSpeed": "3级" + }, + { + "hours": "04时", + "wea": "阴", + "weaImg": "yin", + "tem": "28", + "win": "西南风", + "winSpeed": "3级" + }, + { + "hours": "05时", + "wea": "阴", + "weaImg": "yin", + "tem": "28", + "win": "西南风", + "winSpeed": "3级" + }, + { + "hours": "06时", + "wea": "阴", + "weaImg": "yin", + "tem": "28", + "win": "西南风", + "winSpeed": "3级" + }, + { + "hours": "07时", + "wea": "阴", + "weaImg": "yin", + "tem": "29", + "win": "西南风", + "winSpeed": "3级" + } + ], + "index": [ + { + "title": "湿度", + "level": "45%", + "desc": "湿度刚好。" + }, + { + "title": "体感温度", + "level": "20°", + "desc": "" + }, + { + "title": "风力", + "level": "微风", + "desc": "风力较弱,适宜户外活动。" + }, + { + "title": "风向", + "level": "南风", + "desc": "" + }, + { + "title": "穿衣", + "level": "短袖", + "desc": "建议穿短衫、短裤等清凉夏季服装。" + }, + { + "title": "运动", + "level": "宜室内", + "desc": "" + }, + { + "title": "感冒", + "level": "容易", + "desc": "昼夜温差大,注意预防感冒。" + }, + { + "title": "紫外线", + "level": "弱", + "desc": "辐射弱,涂擦SPF8-12防晒护肤品。" + } + ] + }, + { + "day": "24日(星期五)", + "date": "2022-06-24", + "week": "星期五", + "wea": "多云", + "weaImg": "cloudy", + "weaDay": "多云", + "weaDayImg": "cloudy", + "weaNight": "多云", + "weaNightImg": "cloudy", + "tem": "27", + "tem1": "29", + "tem2": "22", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "西南风", + "西南风" + ], + "winSpeed": "3-4级", + "winMeter": "", + "sunrise": "04:58", + "sunset": "19:04", + "air": "25", + "airLevel": "优", + "airTips": "今天空气很好,适合外出游玩,注意防晒!", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [ + { + "hours": "08时", + "wea": "阴", + "weaImg": "yin", + "tem": "25", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "09时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "27", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "10时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "27", + "win": "西南风", + "winSpeed": "3-4级" + }, + { + "hours": "11时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "28", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "12时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "28", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "13时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "28", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "14时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "27", + "win": "西风", + "winSpeed": "4-5级" + }, + { + "hours": "15时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "27", + "win": "西风", + "winSpeed": "4-5级" + }, + { + "hours": "16时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "26", + "win": "西风", + "winSpeed": "3-4级" + }, + { + "hours": "17时", + "wea": "晴", + "weaImg": "sunny", + "tem": "27", + "win": "北风", + "winSpeed": "3-4级" + }, + { + "hours": "18时", + "wea": "晴", + "weaImg": "sunny", + "tem": "27", + "win": "西风", + "winSpeed": "<3级" + }, + { + "hours": "19时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "26", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "20时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "25", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "21时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "25", + "win": "西南风", + "winSpeed": "<3级" + }, + { + "hours": "22时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "24", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "23时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "24", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "00时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "24", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "01时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "24", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "02时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "24", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "03时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "23", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "04时", + "wea": "多云", + "weaImg": "cloudy", + "tem": "24", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "05时", + "wea": "晴", + "weaImg": "sunny", + "tem": "25", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "06时", + "wea": "晴", + "weaImg": "sunny", + "tem": "25", + "win": "南风", + "winSpeed": "3-4级" + }, + { + "hours": "07时", + "wea": "晴", + "weaImg": "sunny", + "tem": "26", + "win": "南风", + "winSpeed": "3-4级" + } + ], + "index": [ + { + "title": "湿度", + "level": "42%", + "desc": "湿度刚好。" + }, + { + "title": "体感温度", + "level": "25°", + "desc": "" + }, + { + "title": "风力", + "level": "微风", + "desc": "风力较弱,适宜户外活动。" + }, + { + "title": "风向", + "level": "西南风", + "desc": "" + }, + { + "title": "穿衣", + "level": "短袖", + "desc": "建议穿短衫、短裤等清凉夏季服装。" + }, + { + "title": "运动", + "level": "宜室外", + "desc": "" + }, + { + "title": "感冒", + "level": "容易", + "desc": "昼夜温差大,注意预防感冒。" + }, + { + "title": "紫外线", + "level": "弱", + "desc": "辐射弱,涂擦SPF8-12防晒护肤品。" + } + ] + }, + { + "day": "25日(星期六)", + "date": "2022-06-25", + "week": "星期六", + "wea": "多云", + "weaImg": "yun", + "weaDay": "多云", + "weaDayImg": "yun", + "weaNight": "多云", + "weaNightImg": "yun", + "tem": "29", + "tem1": "30", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "无持续风向" + ], + "winSpeed": "4-5级转<3级", + "winMeter": "", + "sunrise": "04:58", + "sunset": "19:04", + "air": "34", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "26日(星期日)", + "date": "2022-06-26", + "week": "星期日", + "wea": "晴", + "weaImg": "sunny", + "weaDay": "晴", + "weaDayImg": "sunny", + "weaNight": "晴", + "weaNightImg": "sunny", + "tem": "36", + "tem1": "40", + "tem2": "30", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "南风" + ], + "winSpeed": "4-5级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "29", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "27日(星期一)", + "date": "2022-06-27", + "week": "星期一", + "wea": "晴", + "weaImg": "sunny", + "weaDay": "晴", + "weaDayImg": "sunny", + "weaNight": "晴", + "weaNightImg": "sunny", + "tem": "33", + "tem1": "39", + "tem2": "28", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "南风", + "南风" + ], + "winSpeed": "4-5级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "26", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "28日(星期二)", + "date": "2022-06-28", + "week": "星期二", + "wea": "多云", + "weaImg": "cloudy", + "weaDay": "多云", + "weaDayImg": "cloudy", + "weaNight": "多云", + "weaNightImg": "cloudy", + "tem": "35", + "tem1": "38", + "tem2": "28", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "西南风", + "南风" + ], + "winSpeed": "4-5级转3-4级", + "winMeter": "", + "sunrise": "04:59", + "sunset": "19:04", + "air": "38", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + }, + { + "day": "29日(星期三)", + "date": "2022-06-29", + "week": "星期三", + "wea": "晴", + "weaImg": "sunny", + "weaDay": "晴", + "weaDayImg": "sunny", + "weaNight": "晴", + "weaNightImg": "sunny", + "tem": "35", + "tem1": "39", + "tem2": "26", + "humidity": "", + "visibility": "", + "pressure": "", + "win": [ + "无持续风向", + "无持续风向" + ], + "winSpeed": "<3级", + "winMeter": "", + "sunrise": "05:00", + "sunset": "19:04", + "air": "31", + "airLevel": "优", + "airTips": "", + "alarm": { + "alarmType": "", + "alarmLevel": "", + "alarmContent": "" + }, + "hours": [], + "index": [] + } + ], + "aqi": { + "updateTime": "13:44", + "cityId": "101210105", + "city": "武汉", + "cityEn": "wuhan", + "country": "中国", + "countryEn": "China", + "air": "29", + "airLevel": "优", + "airTips": "空气很好,可以外出活动,呼吸新鲜空气,拥抱大自然!", + "pm25": "93", + "pm25Desc": "优", + "pm10": "178", + "pm10Desc": "优", + "o3": "17", + "o3Desc": "优", + "no2": "100", + "no2Desc": "优", + "so2": "66", + "so2Desc": "优", + "co": "18", + "coDesc": "-", + "kouzhao": "不用佩戴口罩", + "yundong": "非常适宜运动", + "waichu": "适宜外出", + "kaichuang": "适宜开窗", + "jinghuaqi": "关闭净化器" + } + } +]; + +export class CityFull { + cityId: string = ''; + city: string = ''; + cityEn: string = ''; + country: string = ''; + countryEn: string = ''; + updateTime: string = ''; + data: WeatherItem[] = []; + aqi: Aqi = new Aqi(); +} + +export class WeatherItem { + day: string = ''; + date: string = ''; + week: string = ''; + wea: string = ''; + weaImg: string = ''; + weaDay: string = ''; + weaDayImg: string = ''; + weaNight: string = ''; + weaNightImg: string = ''; + tem: string = ''; + tem1: string = ''; + tem2: string = ''; + humidity: string = ''; + visibility: string = ''; + pressure: string = ''; + win: string[] = []; + winSpeed: string = ''; + winMeter: string = ''; + sunrise: string = ''; + sunset: string = ''; + air: string = ''; + airLevel: string = ''; + airTips: string = ''; + alarm: AlarmItem = new AlarmItem(); + hours: HoursItem[] = []; + index: IndexItem[] = []; +} + +export class AlarmItem { + alarmType: string = ''; + alarmLevel: string = ''; + alarmContent: string = ''; +} + +export class HoursItem { + hours: string = ''; + wea: string = ''; + weaImg: string = ''; + tem: string = ''; + win: string = ''; + winSpeed: string = ''; +} + +export class IndexItem { + title: string = ''; + level: string = ''; + desc: string = ''; +} + +export class Aqi { + updateTime: string = ''; + cityId: string = ''; + city: string = ''; + cityEn: string = ''; + country: string = ''; + countryEn: string = ''; + air: string = ''; + airLevel: string = ''; + airTips: string = ''; + pm25: string = ''; + pm25Desc: string = ''; + pm10: string = ''; + pm10Desc: string = ''; + o3: string = ''; + o3Desc: string = ''; + no2: string = ''; + no2Desc: string = ''; + so2: string = ''; + so2Desc: string = ''; + co: string = ''; + coDesc: string = ''; + kouzhao: string = ''; + yundong: string = ''; + waichu: string = ''; + kaichuang: string = ''; + jinghuaqi: string = ''; +} \ No newline at end of file diff --git a/Weather/common/src/main/ets/mock/RequestData.ets b/Weather/common/src/main/ets/mock/RequestData.ets new file mode 100644 index 0000000000000000000000000000000000000000..bbf6d23bdb30adec8989d0d71efa22bf6849882d --- /dev/null +++ b/Weather/common/src/main/ets/mock/RequestData.ets @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2025 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 FormDate from '../model/FormDate'; +import { AirData, AirIndex, City, CityListData, Forecast, HeaderData, WeekWeather, SuitData } from '../model/Main'; +import { MenuData } from '../model/MenuData'; +import { cityData } from './CityInfo'; +import { Aqi, weather } from './Mock'; + +const form = new FormDate(); // 时间格式修正 + +// 获取天气类型对应的icon +function getTypeIcon(data: string) { + switch (data) { + case '晴': + return $r('app.media.ic_weather_sunny'); + case '多云': + return $r('app.media.ic_weather_cloudy'); + case '阴': + return $r('app.media.ic_weather_yin'); + case '小雨': + return $r('app.media.ic_weather_lightrain'); + case '雷阵雨': + return $r('app.media.ic_weather_lightrain'); + case '日落': + return $r('app.media.ic_weather_sunset'); + case '中雨': + return $r('app.media.ic_weather_rain'); + case '大雨': + return $r('app.media.ic_weather_rain'); + default: + return $r('app.media.ic_weather_cloudy'); + } +} + +function getUpdateTimes() { + let times: string[] = [ + '1小时', + '2小时', + '4小时', + '6小时', + '12小时', + '24小时', + '不更新' + ]; + return times; +} + +function getMenuInfo() { + let data: MenuData[] = + [ + new MenuData('管理城市', 'pages/CityList'), + new MenuData('更新间隔', '') + ]; + return data; +} + +// 获取首页顶部显示信息 +function getHeaderDate(cityIndex: number, city?: City) { + // 生成空气质量对象 + let air: AirData = new AirData(weather[cityIndex].aqi.air, weather[cityIndex].aqi.airLevel); + return new HeaderData(city ? city.name : weather[cityIndex].city, weather[cityIndex].data[1].tem, + weather[cityIndex].data[1].wea, weather[cityIndex].data[1].tem1, weather[cityIndex].data[1].tem2, + getTypeIcon(weather[cityIndex].data[1].wea), air, weather[cityIndex].data[1].airTips); +} + +function getCityList() { + let cities: Array = []; + if (cityData) { + cityData.forEach(item => { + cities.push(new City(item.name, item.temp, item.weather)); + }) + } + return cities; +} + +function addCity(city: City) { + let cities: City[] | undefined = AppStorage.get('cityList'); + let cityIndex = cities!.length % 5; + city.weather = weather[cityIndex].data[1].wea; + city.temp = weather[cityIndex].data[1].tem; + cities!.push(city); + AppStorage.setOrCreate('cityList', cities); +} + +function getCityListWeatherData() { + let cityListWeatherData = new Array(); + // 生成空气质量对象 + + let cities: City[] | undefined = AppStorage.get('cityList'); + if (cities === undefined || cities.length === 0) { + cities = getCityList().splice(0, 2); + AppStorage.setOrCreate('cityList', cities); + } + let titles: string[] = []; + if (cities) { + cities.forEach((item, cityIndex) => { + let index = cityIndex % 5; + let air: AirData = new AirData(weather[cityIndex].aqi.air, weather[cityIndex].aqi.airLevel); + cityListWeatherData.push(new CityListData(item.name, getHeaderDate(index, item), getHoursData(index), + getWeekWeatherData(index), air, getAirIndexData(index), getLifeData(index))); + titles.push(''); + }) + } + AppStorage.setOrCreate('titleText', titles); + return cityListWeatherData; +} + + +// 获取逐小时天气情况 +function getHoursData(cityIndex: number) { + let hoursData = new Array(); + weather[cityIndex].data[1].hours.forEach(item => { + let time = item.hours.substring(0, item.hours.length - 1); + hoursData.push(new Forecast(`${item.tem}°`, `${time}:00`, form.formTimeSlot(parseInt(time)), getTypeIcon(item.wea), + item.win, item.winSpeed)); + if (item.hours.indexOf('17') !== -1) { + hoursData.push(new Forecast('日落', '17:32', form.formTimeSlot(parseInt(time)), getTypeIcon('日落'), item.win, + item.winSpeed)); + } + }) + return hoursData; +} + +// 获取一周天气情况 根据获取到的数据格式化成需要的样式 +function getWeekWeatherData(cityIndex: number) { + let weekData = new Array(); + weather[cityIndex].data.forEach(item => { + weekData.push(new WeekWeather(form.formMonthDay(item.date), item.week, getTypeIcon(item.wea), item.wea, + item.airLevel, item.tem1, item.tem2)); + }) + return weekData; +} + +// 获取首页空气质量部分 右侧数据 +function getAirIndexData(cityIndex: number) { + let aqi: Aqi = weather[cityIndex].aqi; + let indexDate: AirIndex[] = [ + new AirIndex('PM10', aqi.pm10), + new AirIndex('PM2.5', aqi.pm25), + new AirIndex('NO2', aqi.no2), + new AirIndex('SO2', aqi.so2), + new AirIndex('O2', aqi.o3), + new AirIndex('CO', aqi.co) + ]; + return indexDate; +} + +// 获取生活指数 下方数据 +function getLifeData(cityIndex: number) { + let suitDate: SuitData[] = new Array(); + let iconList = [ + $r('app.media.icon_humidity'), + $r('app.media.icon_cloth'), + $r('app.media.icon_temperature'), + $r('app.media.icon_sport'), + $r('app.media.icon_breeze'), + $r('app.media.icon_cold'), + $r('app.media.icon_southerly'), + $r('app.media.icon_uv') + ]; + weather[cityIndex].data[1].index.forEach((item, index) => { + suitDate.push(new SuitData(iconList[index], item.title, item.level)); + }) + return suitDate; +} + +// 根据天气类型 获取背景图片 +function getSideBg(weatherType: string) { + if (weatherType === '晴') { + return $r('app.media.weather_fine'); + } else if (weatherType.includes('雨')) { + return $r('app.media.weather_rain'); + } else { + return $r('app.media.weather_yin'); + } +} + + +// 根据天气类型 获取背景图片 +function getBg(weatherType: string) { + if (weatherType === '晴') { + return $r('app.media.sunny_bg'); + } else if (weatherType.includes('雨')) { + return $r('app.media.rain_bg'); + } else { + return $r('app.media.yin_bg'); + } +} + +export { + getUpdateTimes, + getMenuInfo, + getHeaderDate, + getCityList, + addCity, + getCityListWeatherData, + getHoursData, + getWeekWeatherData, + getAirIndexData, + getLifeData, + getSideBg, + getBg +}; \ No newline at end of file diff --git a/Weather/common/src/main/ets/model/BasicDataSource.ets b/Weather/common/src/main/ets/model/BasicDataSource.ets new file mode 100644 index 0000000000000000000000000000000000000000..ec8fe597edd7e87cab1563cb638b296539078910 --- /dev/null +++ b/Weather/common/src/main/ets/model/BasicDataSource.ets @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2025 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. + */ + +class BasicDataSource implements IDataSource { + listeners: DataChangeListener[] = []; + + public totalCount(): number { + return 0; + } + + public getData(index: number): T | undefined { + return undefined; + } + + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + console.info('add listener'); + this.listeners.push(listener); + } + } + + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + console.info('remove listener'); + this.listeners.splice(pos, 1); + } + } + + notifyDataReload(): void { + this.listeners.forEach(listener => { + listener.onDataReloaded(); + }) + } + + notifyDataAdd(index: number): void { + this.listeners.forEach(listener => { + listener.onDataAdd(index); + }) + } + + notifyDataChange(index: number): void { + this.listeners.forEach(listener => { + listener.onDataChange(index); + }) + } + + notifyDataDelete(index: number): void { + this.listeners.forEach(listener => { + listener.onDataDelete(index); + }) + } + + notifyDataMove(from: number, to: number): void { + this.listeners.forEach(listener => { + listener.onDataMove(from, to); + }) + } +} + +export class MyDataSource extends BasicDataSource { + dataArray: T[] = []; + + constructor(data: T[]) { + super(); + this.dataArray = data; + } + + public totalCount(): number { + return this.dataArray.length; + } + + public getData(index: number): T { + return this.dataArray[index]; + } + + public addData(index: number, data: T): void { + this.dataArray.splice(index, 0, data); + this.notifyDataAdd(index); + } + + public pushData(data: T): void { + this.dataArray.push(data); + this.notifyDataAdd(this.dataArray.length - 1); + } +} \ No newline at end of file diff --git a/Weather/common/src/main/ets/model/FormDate.ets b/Weather/common/src/main/ets/model/FormDate.ets new file mode 100644 index 0000000000000000000000000000000000000000..d5d1424bc62778e9e283426dc58b487e12ed11f7 --- /dev/null +++ b/Weather/common/src/main/ets/model/FormDate.ets @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2025 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. + */ + +// 时间格式 调整 +export default class FormDate { + // 月+日 + formMonthDay(goal?: string) { + let date = goal ? new Date(goal) : new Date(); + return `${this.fill(date.getMonth() + 1)}/${date.getDate()}`; + } + + // 换算当前星期几 + formDay(): string { + let day = new Date().getDay(); + if (day === 1) { + return '星期一'; + } else if (day === 2) { + return '星期二'; + } else if (day === 3) { + return '星期三'; + } else if (day === 4) { + return '星期四'; + } else if (day === 5) { + return '星期五'; + } else if (day === 6) { + return '星期六'; + } else if (day === 7) { + return '星期日'; + } + return '星期一'; + } + + // 格式化 当前分钟 + fill(num: number) { + return num > 9 ? '' : '0' + num; + } + + // 当前时间节点称谓 + formTimeSlot(hour?: number): string { + let now = hour ? hour : new Date().getHours(); + if (now >= 0 && now <= 8) { + return '早上'; + } else if (now >= 9 && now < 11) { + return '上午'; + } else if (now >= 11 && now <= 13) { + return '中午'; + } else if (now >= 14 && now <= 16) { + return '下午'; + } else if (now >= 17 && now <= 19) { + return '傍晚'; + } else if (now >= 19 && now <= 23) { + return '晚上'; + } + return '早上'; + } +} \ No newline at end of file diff --git a/Weather/common/src/main/ets/model/Main.ets b/Weather/common/src/main/ets/model/Main.ets new file mode 100644 index 0000000000000000000000000000000000000000..94a13d6a84f956d26107414cf574385b8cd15e12 --- /dev/null +++ b/Weather/common/src/main/ets/model/Main.ets @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2025 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. + */ + +// 预测 气象列表 +class Forecast { + public degree: string; + public date: string; + public desc: string; + public icon: Resource | string; + public win: string; + public winSpeed: string; + + constructor(degree: string, date: string, desc: string, icon: Resource | string, win: string, winSpeed: string) { + this.degree = degree; + this.date = date; + this.desc = desc; + this.icon = icon; + this.win = win; + this.winSpeed = winSpeed; + } +} + +// 一周天气 +class WeekWeather { + public date: string; + public week: string; + public icon: Resource | string; + public weather: string; + public airLevel: string; + public max: string; + public min: string; + + constructor(date: string, week: string, icon: Resource | string, weather: string, airLevel: string, max: string, + min: string) { + this.date = date; + this.week = week; + this.icon = icon; + this.weather = weather; + this.airLevel = airLevel; + this.max = max; + this.min = min; + } +} + +// 空气质量 +class AirIndex { + public index: string; + public figure: string; + + constructor(index: string, figure: string) { + this.index = index; + this.figure = figure; + } +} + +// 舒适度 +class SuitData { + public src: Resource; + public desc: string; + public value: string; + + constructor(src: Resource, desc: string, value: string) { + this.src = src; + this.desc = desc; + this.value = value; + } +} + +// canvas里数据 +class AirData { + public airQuality: string; + public airDesc: string; + + constructor(airQuality: string, airDesc: string) { + this.airQuality = airQuality; + this.airDesc = airDesc; + } +} + +class HeaderData { + public city: string; + public temp: string; + public weatherType: string; + public max: string; + public min: string; + public icon: Resource | string; + public airData: AirData; + public airTips: string; + + constructor(city: string, temp: string, weatherType: string, max: string, min: string, icon: Resource | string, + airData: AirData, + airTips: string) { + this.city = city; + this.temp = temp; + this.weatherType = weatherType; + this.max = max; + this.min = min; + this.icon = icon; + this.airData = airData; + this.airTips = airTips; + } +} + +// city里数据 +class City { + public name: string; + public temp: string; + public weather: string; + + constructor(name: string, temp: string, weather: string) { + this.name = name; + this.temp = temp; + this.weather = weather; + } +} + +class CityListData { + public city: string; + public header: HeaderData; + public hoursData: Forecast[]; + public weekData: WeekWeather[]; + public airData: AirData; + public airIndex: AirIndex[]; + public suitDate: SuitData[]; + + constructor(city: string, header: HeaderData, hoursData: Forecast[], weekData: WeekWeather[], airData: AirData, + airIndex: AirIndex[], suitDate: SuitData[]) { + this.city = city; + this.header = header; + this.hoursData = hoursData; + this.weekData = weekData; + this.airData = airData; + this.airIndex = airIndex; + this.suitDate = suitDate; + } +} + + +export { HeaderData, CityListData, Forecast, AirIndex, SuitData, WeekWeather, AirData, City } \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/ohosTest/ets/test/List.test.ets b/Weather/common/src/main/ets/model/MenuData.ets similarity index 70% rename from AdaptiveCapabilities/entry/src/ohosTest/ets/test/List.test.ets rename to Weather/common/src/main/ets/model/MenuData.ets index 27c07a1a174f6862ea84c4bb5f45bc1789234441..eb30522a483b85799d3d5415dfe393cb16a43195 100644 --- a/AdaptiveCapabilities/entry/src/ohosTest/ets/test/List.test.ets +++ b/Weather/common/src/main/ets/model/MenuData.ets @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 @@ -13,8 +13,13 @@ * limitations under the License. */ -import abilityTest from './Ability.test' +// 首页弹窗菜单 menu数据 +export class MenuData { + public title: string; + public url: string; -export default function testsuite() { - abilityTest() + constructor(title: string, url: string) { + this.title = title; + this.url = url; + } } \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/ohosTest/module.json5 b/Weather/common/src/main/ets/util/Logger.ets similarity index 37% rename from AdaptiveCapabilities/entry/src/ohosTest/module.json5 rename to Weather/common/src/main/ets/util/Logger.ets index a0cc6bc615483b227c75e72f393e087ff0893f16..f06b48312f436492f1afae3b98c8e030b17d643e 100644 --- a/AdaptiveCapabilities/entry/src/ohosTest/module.json5 +++ b/Weather/common/src/main/ets/util/Logger.ets @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 @@ -13,40 +13,26 @@ * limitations under the License. */ -{ - "module": { - "name": "entry_test", - "type": "feature", - "description": "$string:module_test_desc", - "mainElement": "TestAbility", - "deviceTypes": [ - "default", - "tablet" - ], - "deliveryWithInstall": true, - "installationFree": false, - "pages": "$profile:test_pages", - "abilities": [ - { - "name": "TestAbility", - "srcEntry": "./ets/testability/TestAbility.ets", - "description": "$string:TestAbility_desc", - "icon": "$media:icon", - "label": "$string:TestAbility_label", - "visible": true, - "startWindowIcon": "$media:icon", - "startWindowBackground": "$color:start_window_background", - "skills": [ - { - "actions": [ - "action.system.home" - ], - "entities": [ - "entity.system.home" - ] - } - ] - } - ] +import { hilog } from "@kit.PerformanceAnalysisKit"; + +export class Logger { + static PREFIX: string = '[Sample_Weather]'; + static DOMAIN: number = 0xFF00; + static FORMAT: string = '%{public}s, %{public}s'; + + static debug(...args: string[]) { + hilog.debug(Logger.DOMAIN, Logger.PREFIX, Logger.FORMAT, args); + } + + static info(...args: string[]) { + hilog.info(Logger.DOMAIN, Logger.PREFIX, Logger.FORMAT, args); + } + + static warn(...args: string[]) { + hilog.warn(Logger.DOMAIN, Logger.PREFIX, Logger.FORMAT, args); + } + + static error(...args: string[]) { + hilog.error(Logger.DOMAIN, Logger.PREFIX, Logger.FORMAT, args); } -} +} \ No newline at end of file diff --git a/Weather/common/src/main/ets/util/Style.ets b/Weather/common/src/main/ets/util/Style.ets new file mode 100644 index 0000000000000000000000000000000000000000..c1c1107743108fbf7dadf1cc8477d688386b76fe --- /dev/null +++ b/Weather/common/src/main/ets/util/Style.ets @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025 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. + */ + +export class Style { + /** + * Grid item card height. + */ + static readonly CARD_HEIGHT = 192; + /** + * List item weather width. + */ + static readonly WEATHER_ITEM_WIDTH = 80; + /** + * normal padding. + */ + static readonly NORMAL_PADDING = 14; + /** + * normal margin. + */ + static readonly NORMAL_MARGIN = 14; + /** + * normal space. + */ + static readonly NORMAL_SPACE = 12; + /** + * grid gutter + */ + static readonly GRID_GUTTER = 12; + /** + * normal radius. + */ + static readonly NORMAL_RADIUS = 16; + /** + * normal radius. + */ + static readonly CITY_TEXT_RADIUS = 18; + /** + * normal margin. + */ + static readonly ADD_CITY_BOTTOM = 6; + /** + * normal margin. + */ + static readonly ADD_CITY_BOTTOM_LG = 28; + /** + * card background color. + */ + static readonly CARD_BACKGROUND_COLOR = '#24FFFFFF'; + /** + * dialog padding out. + */ + static readonly DIALOG_PADDING_OUT = 42; + /** + * dialog padding. + */ + static readonly DIALOG_PADDING = 24; + /** + * weather big text weight. + */ + static readonly BIG_FONT_WEIGHT = 300; + /** + * time list height. + */ + static readonly TIME_LIST_HEIGHT = 48; + /** + * time list height. + */ + static readonly TIME_LIST_MARGIN = 22; +} \ No newline at end of file diff --git a/Weather/common/src/main/module.json5 b/Weather/common/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3a26ade95efbe0e73d8a7223935b9538cb70684e --- /dev/null +++ b/Weather/common/src/main/module.json5 @@ -0,0 +1,10 @@ +{ + "module": { + "name": "common", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ] + } +} diff --git a/AdaptiveCapabilities/entry/src/ohosTest/resources/base/element/float.json b/Weather/common/src/main/resources/base/element/float.json similarity index 33% rename from AdaptiveCapabilities/entry/src/ohosTest/resources/base/element/float.json rename to Weather/common/src/main/resources/base/element/float.json index aa689d3f32d2b0285889e5c4e8419f01d74cb85f..33ea22304f9b1485b5f22d811023701b5d4e35b6 100644 --- a/AdaptiveCapabilities/entry/src/ohosTest/resources/base/element/float.json +++ b/Weather/common/src/main/resources/base/element/float.json @@ -1,8 +1,8 @@ { "float": [ { - "name": "my_float", - "value": "60vp" + "name": "page_text_font_size", + "value": "50fp" } ] -} \ No newline at end of file +} diff --git a/Weather/common/src/main/resources/base/element/string.json b/Weather/common/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f51a9c8461a55f6312ef950344e3145b7f82d607 --- /dev/null +++ b/Weather/common/src/main/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from package" + } + ] +} diff --git a/Weather/common/src/main/resources/base/media/ic_weather_cloudy.svg b/Weather/common/src/main/resources/base/media/ic_weather_cloudy.svg new file mode 100644 index 0000000000000000000000000000000000000000..65a991a27bddaf77938e28cbdee40c79b314f704 --- /dev/null +++ b/Weather/common/src/main/resources/base/media/ic_weather_cloudy.svg @@ -0,0 +1,28 @@ + + + ic_weather_cloudy + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/ic_weather_lightrain.svg b/Weather/common/src/main/resources/base/media/ic_weather_lightrain.svg new file mode 100644 index 0000000000000000000000000000000000000000..f33d6a8c0fe16f985b8bc1391cef36692cc3c5d7 --- /dev/null +++ b/Weather/common/src/main/resources/base/media/ic_weather_lightrain.svg @@ -0,0 +1,20 @@ + + + ic_weather_lightrain + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/ic_weather_night.svg b/Weather/common/src/main/resources/base/media/ic_weather_night.svg new file mode 100644 index 0000000000000000000000000000000000000000..f411cf47c18dd83314d6f181b057c33a39d4150c --- /dev/null +++ b/Weather/common/src/main/resources/base/media/ic_weather_night.svg @@ -0,0 +1,13 @@ + + + ic_weather_night + + + + + + + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/ic_weather_rain.svg b/Weather/common/src/main/resources/base/media/ic_weather_rain.svg new file mode 100644 index 0000000000000000000000000000000000000000..0a0b902f56fd6e026ad5b87f296005d97edc785d --- /dev/null +++ b/Weather/common/src/main/resources/base/media/ic_weather_rain.svg @@ -0,0 +1,21 @@ + + + ic_weather_rain + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/ic_weather_sunny.svg b/Weather/common/src/main/resources/base/media/ic_weather_sunny.svg new file mode 100644 index 0000000000000000000000000000000000000000..3ee9787874c2d671522f1a336c0010ef32c70d18 --- /dev/null +++ b/Weather/common/src/main/resources/base/media/ic_weather_sunny.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/ic_weather_sunset.svg b/Weather/common/src/main/resources/base/media/ic_weather_sunset.svg new file mode 100644 index 0000000000000000000000000000000000000000..e2222ee9c0bbb47a608ed35b0fb889dabca608e7 --- /dev/null +++ b/Weather/common/src/main/resources/base/media/ic_weather_sunset.svg @@ -0,0 +1,22 @@ + + + ic_weather_sunset + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/ic_weather_yin.svg b/Weather/common/src/main/resources/base/media/ic_weather_yin.svg new file mode 100644 index 0000000000000000000000000000000000000000..efc066cb9302c9f8c9264400528aa7dad84e2cbb --- /dev/null +++ b/Weather/common/src/main/resources/base/media/ic_weather_yin.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/icon_breeze.svg b/Weather/common/src/main/resources/base/media/icon_breeze.svg new file mode 100644 index 0000000000000000000000000000000000000000..e1edcd2bf6cb9011c4918fe0ea23fcee3e1994fc --- /dev/null +++ b/Weather/common/src/main/resources/base/media/icon_breeze.svg @@ -0,0 +1,7 @@ + + + icon_breeze + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/icon_cloth.svg b/Weather/common/src/main/resources/base/media/icon_cloth.svg new file mode 100644 index 0000000000000000000000000000000000000000..57187f177b9b4a28e14423c5d1bbdf6e0cfc2975 --- /dev/null +++ b/Weather/common/src/main/resources/base/media/icon_cloth.svg @@ -0,0 +1,10 @@ + + + icon_cloth + + + + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/icon_cold.svg b/Weather/common/src/main/resources/base/media/icon_cold.svg new file mode 100644 index 0000000000000000000000000000000000000000..38e8867f4f361ff1fb93252f50dade32beab54aa --- /dev/null +++ b/Weather/common/src/main/resources/base/media/icon_cold.svg @@ -0,0 +1,9 @@ + + + icon_cold + + + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/icon_humidity.svg b/Weather/common/src/main/resources/base/media/icon_humidity.svg new file mode 100644 index 0000000000000000000000000000000000000000..014bf10b7d3a4b35b860117c3b99e34be1f77dc8 --- /dev/null +++ b/Weather/common/src/main/resources/base/media/icon_humidity.svg @@ -0,0 +1,8 @@ + + + icon_humidity + + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/icon_southerly.svg b/Weather/common/src/main/resources/base/media/icon_southerly.svg new file mode 100644 index 0000000000000000000000000000000000000000..b331a5d91bd2b85a5c15a3252002ee1b1549d62a --- /dev/null +++ b/Weather/common/src/main/resources/base/media/icon_southerly.svg @@ -0,0 +1,9 @@ + + + icon_southerly + + + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/icon_sport.svg b/Weather/common/src/main/resources/base/media/icon_sport.svg new file mode 100644 index 0000000000000000000000000000000000000000..df9a4fa1b472239bf8f5ad5dc6d7006cf9e1c622 --- /dev/null +++ b/Weather/common/src/main/resources/base/media/icon_sport.svg @@ -0,0 +1,9 @@ + + + icon_sport + + + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/icon_temperature.svg b/Weather/common/src/main/resources/base/media/icon_temperature.svg new file mode 100644 index 0000000000000000000000000000000000000000..31dd5d299b8ac06d42c9fbc6ea9908d852446c55 --- /dev/null +++ b/Weather/common/src/main/resources/base/media/icon_temperature.svg @@ -0,0 +1,7 @@ + + + icon_temperature + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/icon_uv.svg b/Weather/common/src/main/resources/base/media/icon_uv.svg new file mode 100644 index 0000000000000000000000000000000000000000..35a4bd6256dfa36f01b086c94d118f996e31721e --- /dev/null +++ b/Weather/common/src/main/resources/base/media/icon_uv.svg @@ -0,0 +1,7 @@ + + + icon_UV + + + + \ No newline at end of file diff --git a/Weather/common/src/main/resources/base/media/rain_bg.png b/Weather/common/src/main/resources/base/media/rain_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..7045e4b61b0d77efb249c5dbed2b6feddc38b9b4 Binary files /dev/null and b/Weather/common/src/main/resources/base/media/rain_bg.png differ diff --git a/Weather/common/src/main/resources/base/media/sunny_bg.png b/Weather/common/src/main/resources/base/media/sunny_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..55ed10488b0a513b03ca8332d77b8f762be2cd15 Binary files /dev/null and b/Weather/common/src/main/resources/base/media/sunny_bg.png differ diff --git a/Weather/common/src/main/resources/base/media/weather_fine.png b/Weather/common/src/main/resources/base/media/weather_fine.png new file mode 100644 index 0000000000000000000000000000000000000000..2912d93b70470ce7d81ada7d52c5f7f0b29d1918 Binary files /dev/null and b/Weather/common/src/main/resources/base/media/weather_fine.png differ diff --git a/Weather/common/src/main/resources/base/media/weather_rain.png b/Weather/common/src/main/resources/base/media/weather_rain.png new file mode 100644 index 0000000000000000000000000000000000000000..dada5b0f1dde1770d5b69c787526160b27c9a4f9 Binary files /dev/null and b/Weather/common/src/main/resources/base/media/weather_rain.png differ diff --git a/Weather/common/src/main/resources/base/media/weather_yin.png b/Weather/common/src/main/resources/base/media/weather_yin.png new file mode 100644 index 0000000000000000000000000000000000000000..76d5bc5179bd544b1740f1f734201aa925efa037 Binary files /dev/null and b/Weather/common/src/main/resources/base/media/weather_yin.png differ diff --git a/Weather/common/src/main/resources/base/media/yin_bg.png b/Weather/common/src/main/resources/base/media/yin_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..240800a0422d39ccd2405b81b73fc2f76e90fd8f Binary files /dev/null and b/Weather/common/src/main/resources/base/media/yin_bg.png differ diff --git a/Weather/hvigor/hvigor-config.json5 b/Weather/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..6f008c99c91ca502036e67232e4c089e0421aefc --- /dev/null +++ b/Weather/hvigor/hvigor-config.json5 @@ -0,0 +1,22 @@ +{ + "modelVersion": "5.1.1", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/Weather/hvigorfile.ts b/Weather/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..47113e2e36ecefde41c136272a0bd6ff745cffe4 --- /dev/null +++ b/Weather/hvigorfile.ts @@ -0,0 +1,6 @@ +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/Weather/oh-package.json5 b/Weather/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..052cc24d6e7b3f754ab5557652fd9db52c4c2549 --- /dev/null +++ b/Weather/oh-package.json5 @@ -0,0 +1,10 @@ +{ + "modelVersion": "5.1.1", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.21", + "@ohos/hamock": "1.0.0" + } +} diff --git a/Weather/product/default/build-profile.json5 b/Weather/product/default/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4d611879c7913fb0610c686e2399258ab3a6dad1 --- /dev/null +++ b/Weather/product/default/build-profile.json5 @@ -0,0 +1,28 @@ +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/Weather/product/default/hvigorfile.ts b/Weather/product/default/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..b0e3a1ab98a91bc918d6404b2413111a5011f14a --- /dev/null +++ b/Weather/product/default/hvigorfile.ts @@ -0,0 +1,6 @@ +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins: [] /* Custom plugin to extend the functionality of Hvigor. */ +} \ No newline at end of file diff --git a/Weather/product/default/obfuscation-rules.txt b/Weather/product/default/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/Weather/product/default/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/Weather/product/default/oh-package.json5 b/Weather/product/default/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..fb00bfb2008e04a4c60a7f1fe4c368d539d7faf4 --- /dev/null +++ b/Weather/product/default/oh-package.json5 @@ -0,0 +1,11 @@ +{ + "name": "default", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "common": "file:../../common" + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/entryability/EntryAbility.ets b/Weather/product/default/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..a1af16c884471cbd6c5c07e1420b50d9d58d0cf6 --- /dev/null +++ b/Weather/product/default/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,48 @@ +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + let mainWindow: window.Window = windowStage.getMainWindowSync(); + mainWindow.setImmersiveModeEnabledState(true); + mainWindow.setWindowSystemBarEnable([]); + + windowStage.loadContent('pages/Home', (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.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/entrybackupability/EntryBackupAbility.ets b/Weather/product/default/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..8e4de99282050bad799ac892eb85ac5449364a51 --- /dev/null +++ b/Weather/product/default/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,16 @@ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/feature/AirQualityFeature.ets b/Weather/product/default/src/main/ets/feature/AirQualityFeature.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ed678dada870c5700ef8900c9e62c81ecbaf3d1 --- /dev/null +++ b/Weather/product/default/src/main/ets/feature/AirQualityFeature.ets @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025 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 { AirData } from 'common'; + +export function initRound(context: CanvasRenderingContext2D, air: AirData) { + let width = context.width; + let height = context.height; + // 百分比转换 + let percent = Number.parseInt(air.airQuality) * 2 / 100 + 0.5; + // 背景 + context.save(); + context.beginPath(); + context.lineWidth = 8; + context.lineCap = 'round'; + context.strokeStyle = '#33FFFFFF'; + context.arc(width / 2, width / 2, width / 2 - 10, Math.PI * 0.3, Math.PI * 0.7, true); + context.stroke(); + context.closePath(); + context.restore(); + + // 绘制圆环 + context.save(); + context.lineWidth = 8; + context.lineCap = 'round'; + context.beginPath(); + // 渐变色 + let color = context.createLinearGradient(0, 0, width, height); + color.addColorStop(0, '#AED34A'); + color.addColorStop(0.5, '#82CD61'); + color.addColorStop(1, '#82CD61'); + context.strokeStyle = color; + + context.arc(width / 2, width / 2, width / 2 - 10, Math.PI * 0.7, Math.PI * percent, false); + context.stroke(); + context.closePath(); + context.restore(); + + // 中间文字 + context.font = '22px'; + context.fillStyle = '#FFFFFF'; + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.fillText(air.airDesc, width / 2, height / 2 - 20); + + // 中间文字 + context.font = '48px'; + context.fillStyle = '#FFFFFF'; + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.fillText(air.airQuality, width / 2, height / 2 + 5); + + context.font = '20px'; + context.fillStyle = '#99FFFFFF'; + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.fillText('0', width / 2 - 30, height - 5); + + context.font = '20px'; + context.fillStyle = "#99FFFFFF"; + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.fillText('500', width / 2 + 25, height - 5); +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/feature/SunCanvasFeature.ets b/Weather/product/default/src/main/ets/feature/SunCanvasFeature.ets new file mode 100644 index 0000000000000000000000000000000000000000..26e3fea9b175d3c3f5b6c9c21f4b87edc8d9283f --- /dev/null +++ b/Weather/product/default/src/main/ets/feature/SunCanvasFeature.ets @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2025 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. + */ + +/** + * 日出日落图 + * @param context + * @param img + */ +function initSun(context: CanvasRenderingContext2D, img: ImageBitmap) { + /* + * 根据日出日落时间点绘制 + * 获取两个时间点 + * 分割成一个半圆 + * 角度换算刻度 + * 绘制 + */ + + let begin = '日出 早上6:00'; + let final = '日落 傍晚5:32'; + let now = new Date(); + let time: number = now.getHours(); + let flag = true; // 太阳是否绘制 + let scale: number = Math.floor((time - 6) * 18 / 11); + if (now.getHours() < 6 || now.getHours() >= 17) { + flag = false; + scale = 0; + } + + let width = context.width, height = context.height; + + + // 下线 + context.beginPath(); + context.strokeStyle = "#33FFFFFF"; + context.setLineDash([]); + context.moveTo(0, height - 54); + context.lineTo(width, height - 54); + context.stroke(); + + // 文字 + context.font = '20px'; + context.fillStyle = "#99FFFFFF"; + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.fillText(begin, width / 6, height - 40); + + context.font = '20px'; + context.fillStyle = "#99FFFFFF"; + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.fillText(final, width / 6 * 5, height - 40); + + // 渐变色 + let color = context.createLinearGradient(0, 0, width, height); + color.addColorStop(0, '#FFAF38'); + color.addColorStop(scale / 18, '#DDFAD961'); + color.addColorStop(1, '#11FFFFFF'); + context.save(); + context.beginPath(); + context.lineWidth = 1; + if (flag) { + context.strokeStyle = color; + } else { + context.strokeStyle = '#33C0C0C0'; + } + context.arc(width / 2, height - 25, width * 0.4, Math.PI / 180 * 193, Math.PI * 2 / 180 * 173, false); + context.setLineDash([8]); + context.stroke(); + context.restore(); + + if (flag) { + // x为刻度线 + context.save(); + // 弧度*π/180 得到弧度 + let deg = Math.PI / 180 * (193 + scale * 9); + let offsetX = -(Math.cos(deg) * width * 0.4); + let offsetY = -(Math.sin(deg) * width * 0.40); + + context.drawImage(img, 0, 0, 120, 120, width / 2 - offsetX - 12, height - 37 - offsetY, 24, 24); + } +} + +/** + * 月出月落图 + * @param context + * @param img + * @param iconMoon + */ +function initMoon(context: CanvasRenderingContext2D, img: ImageBitmap, iconMoon: ImageBitmap) { + /* + * 根据月出月落时间点绘制 + * 获取两个时间点 + * 分割成一个半圆 + * 角度换算刻度 + * 绘制 + */ + + let begin = '月出 傍晚5:12'; + let final = '月落 早上6:20'; + let now = new Date(); + let time: number = now.getHours(); + let flag = true; // 月亮是否绘制 + let index: number = time >= 17 ? time - 17 : time + 7; + let scale = Math.floor(index * 18 / 13); + if (now.getHours() >= 6 && now.getHours() < 17) { + flag = false; + scale = 0; + } + + let width = context.width, height = context.height; + + // 文字 + context.font = '20px'; + context.fillStyle = "#99FFFFFF"; + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.fillText(begin, width / 6, height - 20); + + context.font = '20px'; + context.fillStyle = "#99FFFFFF"; + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.fillText('上弦月', width / 2, height - 20); + + context.font = '20px'; + context.fillStyle = "#99FFFFFF"; + context.textAlign = 'center'; + context.textBaseline = 'middle'; + context.fillText(final, width / 6 * 5, height - 20); + + context.drawImage(iconMoon, 0, 0, 16, 16, width / 2 - 5, height - 45, 24, 24); + + // 渐变色 + let color = context.createLinearGradient(0, 0, width, height); + color.addColorStop(0, '#FFAF38'); + color.addColorStop(scale / 18, '#DDFAD961'); + color.addColorStop(1, '#11FFFFFF'); + context.save(); + context.beginPath(); + context.lineWidth = 1; + if (flag) { + context.strokeStyle = color; + } else { + context.strokeStyle = '#33C0C0C0'; + } + context.arc(width / 2, height - 25, width * 0.3, Math.PI / 180 * 197, Math.PI * 2 / 180 * 171, false); + context.setLineDash([8]); + context.stroke(); + context.restore(); + + if (flag) { + // x为刻度线 + context.save(); + // 弧度*π/180 得到弧度 + let deg = Math.PI / 180 * (197 + scale * 9); + let offsetX = -(Math.cos(deg) * width * 0.3); + let offsetY = -(Math.sin(deg) * width * 0.3); + + context.drawImage(img, 0, 0, 120, 120, width / 2 - offsetX - 12, height - 37 - offsetY, 24, 24); + } +} + +export { initSun, initMoon }; \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/AddCity.ets b/Weather/product/default/src/main/ets/pages/AddCity.ets new file mode 100644 index 0000000000000000000000000000000000000000..099994fde522994f43757f9496200f140cdd0e06 --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/AddCity.ets @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2025 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 { router } from '@kit.ArkUI'; +import { addCity, City, getCityList, MyDataSource, Style } from 'common'; + +@Entry +@Component +struct AddCity { + build() { + Column() { + Row() { + Image($r('app.media.icon_back')) + .width(24) + .margin({ left: 26 }) + .objectFit(ImageFit.Contain) + .onClick(() => { + this.getUIContext().getRouter().back(); + }) + Text($r('app.string.add_city')) + .fontSize(20) + .margin({ left: Style.NORMAL_MARGIN }) + } + .width('100%') + .height(56) + + Scroll() { + CityGrid() + } + .layoutWeight(1) + .margin({ top: 18 }) + .scrollBar(BarState.Off) + } + .height('100%') + .backgroundColor('#F1F3F5') + } +} + +@Component +export struct CityGrid { + @StorageLink('cityList') cities: Array = []; + cityList: MyDataSource = new MyDataSource(getCityList()); + + build() { + GridRow({ + columns: { sm: 4, md: 8, lg: 12 }, + breakpoints: { reference: BreakpointsReference.WindowSize } + }) { + GridCol({ + span: { sm: 4, md: 6, lg: 8 }, + offset: { sm: 0, md: 1, lg: 2 } + }) { + GridRow({ + columns: { sm: 3, md: 4, lg: 7 }, + gutter: { x: this.getUIContext().px2vp(17), y: this.getUIContext().px2vp(8) }, + breakpoints: { reference: BreakpointsReference.WindowSize } + }) { + GridCol({ span: { sm: 3, md: 4, lg: 7 } }) { + Text($r('app.string.hot_city')) + .width('100%') + .fontSize(14) + .fontWeight(FontWeight.Regular) + .fontColor('#99000000') + .margin({ bottom: 14 }) + } + + LazyForEach(this.cityList, (item: City) => { + GridCol({ span: 1 }) { + Column() { + Text(item.name) + .fontSize(14) + .fontColor(this.isCityAdded(item) ? '#61000000' : '#000000') + } + .width('100%') + .height(36) + .backgroundColor(this.isCityAdded(item) ? '#05000000' : '#11000000') + .justifyContent(FlexAlign.Center) + .borderRadius(Style.CITY_TEXT_RADIUS) + .onClick(() => { + if (!this.isCityAdded(item)) { + addCity(item); + AppStorage.setOrCreate('isRefresh', true); + this.getUIContext().getRouter().back(); + } + }) + } + }, (item: City, index: number) => JSON.stringify(item) + index) + } + } + .height('100%') + } + .padding({ left: Style.NORMAL_PADDING, right: Style.NORMAL_PADDING }) + } + + isCityAdded(city: City) { + let isAdded: boolean = false; + this.cities.forEach(item => { + if (item.name === city.name) { + isAdded = true; + } + }) + return isAdded; + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/AirQuality.ets b/Weather/product/default/src/main/ets/pages/AirQuality.ets new file mode 100644 index 0000000000000000000000000000000000000000..956d49fa9e8f5396f7bf030388d43a98fbc5d5cd --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/AirQuality.ets @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 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 { AirData, AirIndex, getAirIndexData, getHeaderDate, Style } from 'common'; +import { initRound } from '../feature/AirQualityFeature'; + + +@Preview +@Component +export default struct AirQuality { + settings: RenderingContextSettings = new RenderingContextSettings(true); + context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); + airIndexData: AirIndex[] = getAirIndexData(0); + airData: AirData = getHeaderDate(0).airData; + + build() { + Row() { + Column() { + Text($r('app.string.air_quality')) + .fontSize(13) + .fontColor(Color.White) + .fontWeight(FontWeight.Medium) + Canvas(this.context) + .height('65%') + .aspectRatio(1) + .onReady(() => { + this.context.clearRect(0, 0, this.context.width, this.context.height); + initRound(this.context, this.airData); + }) + } + .width('50%') + .justifyContent(FlexAlign.Center) + + List({ space: 12 }) { + ForEach(this.airIndexData, (item: AirIndex, index: number) => { + ListItem() { + Row() { + Text(item.index) + .width(48) + .fontSize(12) + .fontColor('#99FFFFFF') + Text(item.figure) + .width(48) + .fontSize(12) + .fontColor('#FFFFFF') + .margin({ left: 12 }) + } + .justifyContent(FlexAlign.Center) + } + .width('100%') + }, (item: AirIndex, index: number) => JSON.stringify(item) + index) + } + .width('50%') + .margin({ left: 10 }) + .height('75%') + } + .height(Style.CARD_HEIGHT) + .justifyContent(FlexAlign.Center) + .backgroundColor(Style.CARD_BACKGROUND_COLOR) + .borderRadius(Style.NORMAL_RADIUS) + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/CityList.ets b/Weather/product/default/src/main/ets/pages/CityList.ets new file mode 100644 index 0000000000000000000000000000000000000000..4c88f199fa807a71c1c42ff401d565fd667038dc --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/CityList.ets @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2025 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 { router } from '@kit.ArkUI'; +import { City, getSideBg, MyDataSource, Style } from 'common'; + +@Entry +@Component +struct CityList { + @StorageLink('cityList') cities: Array = []; + @StorageLink('curBp') curBp: string = 'lg'; + cityList: MyDataSource = new MyDataSource(this.cities); + + getOffsetMD(index: number): number { + if (index === 0) { + return 1; + } + if (index % 2 === 0) { + return 2; + } + return 0; + } + + getOffsetLG(index: number): number { + if (index === 0) { + return 2; + } + if (index % 2 === 0) { + return 4; + } + return 0; + } + + @Builder + CityInfo(item: City, index: number) { + Row() { + Text(item.name) + .fontColor(Color.White) + .fontSize(20) + if (index === 0) { + Image($r('app.media.icon_location')) + .size({ width: 16, height: 16 }) + .objectFit(ImageFit.Contain) + } + Blank() + Column() { + Row() { + Text(item.temp) + .fontColor(Color.White) + .fontWeight(Style.BIG_FONT_WEIGHT) + .fontSize(38) + Text($r('app.string.du')) + .fontColor(Color.White) + .fontSize(16) + .margin({ bottom: 22 }) + } + + Text(item.weather) + .fontColor(Color.White) + .fontSize(12) + } + } + .width('100%') + .height(80) + .alignItems(VerticalAlign.Center) + .padding(Style.NORMAL_PADDING) + .borderRadius(Style.NORMAL_RADIUS) + .alignItems(VerticalAlign.Center) + .backgroundImageSize(ImageSize.Cover) + .backgroundImage(getSideBg(item.weather)) + } + + build() { + Column() { + Row() { + Image($r('app.media.icon_back')) + .width(24) + .margin({ left: 26 }) + .objectFit(ImageFit.Contain) + .onClick(() => { + this.getUIContext().getRouter().back(); + }) + Text($r('app.string.manage_city')) + .fontSize(20) + .margin({ left: Style.NORMAL_MARGIN }) + } + .width('100%') + .height(56) + + Scroll() { + GridRow({ columns: { sm: 4, md: 8, lg: 12 }, gutter: { x: Style.GRID_GUTTER, y: Style.GRID_GUTTER } }) { + LazyForEach(this.cityList, (item: City, index: number) => { + GridCol({ + span: { sm: 4, md: 3, lg: 4 }, + offset: { sm: 0, md: this.getOffsetMD(index), lg: this.getOffsetLG(index) } + }) { + this.CityInfo(item, index); + } + }, (item: City, index: number) => JSON.stringify(item) + index) + } + } + .layoutWeight(1) + .margin({ top: 12 }) + .scrollBar(BarState.Off) + .align(Alignment.TopStart) + .padding({ left: Style.NORMAL_PADDING, right: Style.NORMAL_PADDING }) + + Column() { + Image($r('app.media.icon_add')) + .width(24) + .height(24) + .objectFit(ImageFit.Contain) + Text($r('app.string.add_city')) + .fontSize(10) + } + .id('addCity') + .justifyContent(FlexAlign.Center) + .padding({ bottom: this.curBp === 'lg' ? Style.ADD_CITY_BOTTOM_LG : Style.ADD_CITY_BOTTOM }) + .onClick(() => { + this.getUIContext().getRouter().pushUrl({ url: 'pages/AddCity' }); + }) + } + .height('100%') + .backgroundColor('#F1F3F5') + } + + onPageShow() { + this.cityList.dataArray = this.cities; + this.cityList.notifyDataReload(); + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/Home.ets b/Weather/product/default/src/main/ets/pages/Home.ets new file mode 100644 index 0000000000000000000000000000000000000000..29125710c2fb4ef3f87599507ed5a6285bb076fa --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/Home.ets @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2022-2023 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 { mediaquery } from '@kit.ArkUI'; +// Start Home +import HomeContent from './HomeContent'; +import IndexTitleBar from './IndexTitleBar'; +import SideContent from './SideContent'; +import { CityListData, Style, getBg, getCityListWeatherData, Logger } from 'common'; +// StartExclude Home +const TAG: string = 'Home'; +// EndExclude Home + +@Entry +@Component +struct Home { + // StartExclude Home + @StorageLink('isRefresh') @Watch('refreshChange') isRefresh: boolean = false; + @StorageLink('swiperIndex') swiperIndex: number = 0; + // EndExclude Home + @State curBp: string = 'md'; + @State cityListWeatherData: CityListData[] = getCityListWeatherData(); + @State showSideBar: boolean = false; + // StartExclude Home + @State popupState: boolean = false; + smListener: mediaquery.MediaQueryListener = + this.getUIContext().getMediaQuery().matchMediaSync('(320vp { + HomeContent({ showSideBar: this.showSideBar, cityListData: item, index: index }) + }, (item: CityListData, index: number) => JSON.stringify(item) + index) + } + .id('swiper') + .padding({ left: Style.NORMAL_PADDING, right: Style.NORMAL_PADDING }) + .onChange(index => { + this.swiperIndex = index; + AppStorage.setOrCreate('swiperIndex', this.swiperIndex); + }) + // Disable navigation dots on lg width breakpoint. + .indicator(this.curBp !== 'lg' ? new DotIndicator() + .selectedColor(Color.White) : false + ) + .index(this.swiperIndex) + .loop(false) + .width('100%') + .layoutWeight(1) + } + .height('100%') + } + .height('100%') + .sideBarWidth('33.3%') + .minSideBarWidth('33.3%') + .maxSideBarWidth('33.3%') + .showControlButton(false) + .showSideBar(this.showSideBar) + .backgroundImageSize(ImageSize.Cover) + .backgroundImage(getBg(this.cityListWeatherData[this.swiperIndex].header.weatherType)) + } + // StartExclude Home + + aboutToAppear() { + this.smListener.on('change', this.isBreakpointSM); + this.mdListener.on('change', this.isBreakpointMD); + this.lgListener.on('change', this.isBreakpointLG); + } + + aboutToDisappear() { + this.smListener.off('change', this.isBreakpointSM); + this.mdListener.off('change', this.isBreakpointMD); + this.lgListener.off('change', this.isBreakpointLG); + } + + isBreakpointSM = (mediaQueryResult: mediaquery.MediaQueryResult) => { + if (mediaQueryResult.matches) { + this.curBp = 'sm'; + this.showSideBar = false; + AppStorage.setOrCreate('curBp', this.curBp); + } + Logger.info(TAG, `this.curBp = ${this.curBp}`); + } + isBreakpointMD = (mediaQueryResult: mediaquery.MediaQueryResult) => { + if (mediaQueryResult.matches) { + this.curBp = 'md'; + this.showSideBar = false; + AppStorage.setOrCreate('curBp', this.curBp); + } + Logger.info(TAG, `this.curBp = ${this.curBp}`); + } + isBreakpointLG = (mediaQueryResult: mediaquery.MediaQueryResult) => { + if (mediaQueryResult.matches) { + if (this.curBp !== 'lg') { + this.showSideBar = true; + } + this.curBp = 'lg'; + AppStorage.setOrCreate('curBp', this.curBp); + } + Logger.info(TAG, `this.curBp = ${this.curBp}`); + } + + refreshChange() { + Logger.info(TAG, `refreshChange}`); + if (this.isRefresh) { + this.cityListWeatherData = getCityListWeatherData(); + AppStorage.setOrCreate('isRefresh', false); + } + Logger.info(TAG, `refreshChange, this.cityListWeatherData.length = ${this.cityListWeatherData.length}`); + } + // EndExclude Home +} +// End Home \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/HomeContent.ets b/Weather/product/default/src/main/ets/pages/HomeContent.ets new file mode 100644 index 0000000000000000000000000000000000000000..a3526e56c6e5677d4914adeb1633fea373656ae1 --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/HomeContent.ets @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2022-2023 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. + */ + +// Start HomeContent +import AirQuality from './AirQuality'; +import HoursWeather from './HoursWeather'; +import IndexHeader from './IndexHeader'; +import IndexEnd from './IndexEnd'; +import LifeIndex from './LifeIndex'; +import MultidayWeather from './MultidayWeather'; +import SunCanvas from './SunCanvas'; +import { CityListData, Style } from 'common'; + +@Component +export default struct HomeContent { + @Prop showSideBar: boolean; + @StorageLink('titleText') titleText: string[] = []; + @StorageLink('swiperIndex') swiperIndex: number = 0; + @State headerOpacity: number = 1; + cityListData?: CityListData; + index: number = 1; + scroller: Scroller = new Scroller(); + + build() { + Scroll(this.scroller) { + GridRow({ + columns: { + xs: 4, + sm: 4, + md: 8, + lg: this.showSideBar ? 8 : 12 + }, + gutter: { x: Style.GRID_GUTTER, y: Style.GRID_GUTTER }, + breakpoints: { reference: BreakpointsReference.WindowSize } + }) { + // Weather overview. + GridCol({ + span: { + xs: 4, + sm: 4, + md: 8, + lg: this.showSideBar ? 8 : 12 + }, + order: 0 + }) { + IndexHeader({ headerDate: this.cityListData!.header, index: this.index }) + .opacity(this.headerOpacity) + } + + // Hourly weather. + GridCol({ + span: { + xs: 4, + sm: 4, + md: 8, + lg: 8 + }, + order: 1 + }) { + HoursWeather({ hoursData: this.cityListData!.hoursData }) + } + + // Daily weather. + GridCol({ + span: 4, + order: { + xs: 2, + sm: 2, + md: 2, + lg: this.showSideBar ? 2 : 3 + } + },) { + MultidayWeather({ weekData: this.cityListData!.weekData }) + } + + // Air quality. + GridCol({ + span: 4, + order: { + xs: 3, + sm: 3, + md: 3, + lg: this.showSideBar ? 3 : 2 + } + }) { + AirQuality({ airData: this.cityListData!.airData, airIndexData: this.cityListData!.airIndex }) + } + + // Living index. + GridCol({ span: 4, order: 4 }) { + LifeIndex({ lifeData: this.cityListData!.suitDate }) + } + + // Sun canvas. + GridCol({ span: 4, order: 5 }) { + SunCanvas() + } + + // Index end. + GridCol({ + span: { + xs: 4, + sm: 4, + md: 8, + lg: this.showSideBar ? 8 : 12 + }, + order: 6 + }) { + IndexEnd() + } + } + } + // StartExclude HomeContent + .id('homeContent' + this.index) + .width('100%') + .layoutWeight(1) + .scrollBar(BarState.Off) + .onWillScroll(() => { + this.headerOpacity = 1 - (this.scroller.currentOffset().yOffset - 45) / 100; + if (this.scroller.currentOffset().yOffset > 45) { + this.titleText[this.index] = this.cityListData!.header.city; + AppStorage.setOrCreate('titleText', this.titleText); + } else if (this.scroller.currentOffset().yOffset < 45) { + this.titleText[this.index] = ''; + AppStorage.setOrCreate('titleText', this.titleText); + } + }) + // EndExclude HomeContent + } +} +// End HomeContent \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/HoursWeather.ets b/Weather/product/default/src/main/ets/pages/HoursWeather.ets new file mode 100644 index 0000000000000000000000000000000000000000..dbd73786a121591b9049b4bc0c212761598f649d --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/HoursWeather.ets @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025 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. + */ + +// Start HoursWeather +import { Forecast, getHoursData, MyDataSource, Style } from 'common'; + +@Preview +@Component +export default struct HoursWeather { + hoursData: Forecast[] = getHoursData(0); + @State hoursDataResource: MyDataSource = new MyDataSource(this.hoursData); + @StorageLink('curBp') curBp: string = 'lg'; + + // StartExclude HoursWeather + aboutToAppear() { + this.hoursDataResource.dataArray = this.hoursData; + } + + @Builder + HoursWeatherItem(hoursItem: Forecast, itemWidth: number) { + Column() { + Text(`${hoursItem.desc}${hoursItem.date}`) + .fontSize(12) + .fontColor(Color.White) + Row() { + Image(hoursItem.icon) + .width(28) + .height(28) + .objectFit(ImageFit.Contain) + } + .margin({ top: 25 }) + .justifyContent(FlexAlign.Center) + + Text(hoursItem.degree) + .fontSize(14) + .fontColor(Color.White) + .margin({ top: 16 }) + Text(hoursItem.win) + .fontSize(12) + .fontColor(Color.White) + .margin({ top: 16 }) + Text(hoursItem.winSpeed) + .fontSize(12) + .fontColor(Color.White) + .margin({ top: 5 }) + } + .width(itemWidth) + .padding({ top: 18, bottom: 18 }) + } + + // EndExclude HoursWeather + build() { + // Implement extensibility capability through list component. + List() { + LazyForEach(this.hoursDataResource, (hoursItem: Forecast, index: number) => { + ListItem() { + this.HoursWeatherItem(hoursItem, + this.curBp === 'lg' ? Style.WEATHER_ITEM_WIDTH + 2 : Style.WEATHER_ITEM_WIDTH) + } + }, (hoursItem: Forecast, index: number) => JSON.stringify(hoursItem) + index) + } + .width('100%') + .height(Style.CARD_HEIGHT) + .borderRadius(Style.NORMAL_RADIUS) + .backgroundColor(Style.CARD_BACKGROUND_COLOR) + .listDirection(Axis.Horizontal) + } +} +// End HoursWeather \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/ohosTest/ets/testability/pages/Index.ets b/Weather/product/default/src/main/ets/pages/IndexEnd.ets similarity index 42% rename from AdaptiveCapabilities/entry/src/ohosTest/ets/testability/pages/Index.ets rename to Weather/product/default/src/main/ets/pages/IndexEnd.ets index 2b3ab3396b754fc530311944f6eb5459bf03cc32..f79a605b955ac2c682f25aaddb9ead369d2719f1 100644 --- a/AdaptiveCapabilities/entry/src/ohosTest/ets/testability/pages/Index.ets +++ b/Weather/product/default/src/main/ets/pages/IndexEnd.ets @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2025 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 @@ -13,39 +13,36 @@ * limitations under the License. */ -import hilog from '@ohos.hilog'; - -@Entry +@Preview @Component -struct Index { - aboutToAppear() { - hilog.isLoggable(0x0000, 'testTag', hilog.LogLevel.INFO); - hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility index aboutToAppear'); - } - @State message: string = 'Hello World' +export default struct IndexEnd { build() { - Row() { - Column() { - Text(this.message) - .fontSize(50) - .fontWeight(FontWeight.Bold) - Button() { - Text('next page') - .fontSize(20) - .fontWeight(FontWeight.Bold) - } - .type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .backgroundColor('#0D9FFB') - .width('35%') - .height('5%') - .onClick(()=>{ - }) + Column() { + Row() { + Image($r('app.media.icon_china_weather')) + .width(16) + .height(16) + .objectFit(ImageFit.Contain) + .opacity(0.6) + Text($r('app.string.china_weather')) + .fontColor('#99FFFFFF') + .fontSize(12) } - .width('100%') + + Text($r('app.string.weather_version')) + .fontColor('#99FFFFFF') + .fontSize(12) + .margin({ top: 8 }) + Text($r('app.string.weather_statement')) + .fontColor('#FFFFFF') + .fontSize(12) + .margin({ top: 4 }) + Text($r('app.string.weather_copyright')) + .fontColor('#99FFFFFF') + .fontSize(12) + .margin({ top: 4 }) } - .height('100%') + .width('100%') + .padding({ top: 40, bottom: 50 }) } } \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/IndexHeader.ets b/Weather/product/default/src/main/ets/pages/IndexHeader.ets new file mode 100644 index 0000000000000000000000000000000000000000..4b456643dcc139e7159d22ad2756baa42da6bdac --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/IndexHeader.ets @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025 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 { getHeaderDate, HeaderData, Style } from 'common'; + +@Preview +@Component +export default struct IndexHeader { + headerDate: HeaderData = getHeaderDate(0); + index: number = 0; + + build() { + Column() { + Row() { + Text(this.headerDate.city) + .fontColor(Color.White) + .fontWeight(FontWeight.Regular) + .fontSize(18) + if (this.index === 0) { + Image($r('app.media.icon_location')) + .size({ width: 16, height: 16 }) + .objectFit(ImageFit.Contain) + } + } + + Row() { + Text(this.headerDate.temp) + .fontColor(Color.White) + .fontWeight(Style.BIG_FONT_WEIGHT) + .fontSize(96) + Text($r('app.string.du')) + .fontColor(Color.White) + .fontWeight(FontWeight.Regular) + .fontSize(35) + .margin({ bottom: 36 }) + } + .margin({ top: 4 }) + .padding({ left: 35 }) + + Row() { + Text(`${this.headerDate.max}℃ / `) + .fontColor(Color.White) + .fontWeight(FontWeight.Medium) + .fontSize(16) + Text(`${this.headerDate.min}℃`) + .fontColor('#99FFFFFF') + .fontWeight(FontWeight.Medium) + .fontSize(16) + } + .margin({ top: 6 }) + + Row() { + Text(`${this.headerDate.weatherType} `) + .fontColor(Color.White) + .fontWeight(FontWeight.Medium) + .fontSize(16) + Text($r('app.string.air')) + .fontColor(Color.White) + .fontWeight(FontWeight.Medium) + .fontSize(16) + Text(this.headerDate.airData.airDesc) + .fontColor(Color.White) + .fontWeight(FontWeight.Medium) + .fontSize(16) + } + .margin({ top: 6 }) + + Row() { + Image($r('app.media.icon_message')) + .width(24) + .height(24) + .objectFit(ImageFit.Contain) + Text(this.headerDate.airTips) + .fontColor(Color.White) + .fontSize(12) + .margin({ left: 8 }) + } + .width('100%') + .margin({ top: 48 }) + } + .width('100%') + .margin({ top: 30 }) + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/IndexTitleBar.ets b/Weather/product/default/src/main/ets/pages/IndexTitleBar.ets new file mode 100644 index 0000000000000000000000000000000000000000..2b575fc6f314f199954fc1cabe2ffcfd46eae688 --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/IndexTitleBar.ets @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2025 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 { router } from '@kit.ArkUI'; +import UpdateTimeDialog from './UpdateTimeDialog'; +import { getMenuInfo, MenuData, Style } from 'common'; + +@Component +export default struct IndexTitleBar { + @State popupState: boolean = false; + @StorageProp('curBp') @Watch('curBpChange') curBp: string = 'sm'; + @Link showSideBar: boolean; + @StorageLink('titleText') titleText: string[] = []; + @StorageLink('swiperIndex') swiperIndex: number = 0; + showDialog: boolean = false; + dialogController?: CustomDialogController; + + @Builder + popupBuilder() { + Row() { + Column() { + ForEach(getMenuInfo(), (item: MenuData, index: number) => { + if (index > 0) { + Divider() + .width('100%') + .color('#AFAFAF') + .margin({ top: 10, bottom: 10 }) + } + Text(item.title) + .id('menu' + index) + .fontSize(16) + .fontColor('#000000') + .fontWeight(FontWeight.Regular) + .width('100%') + .onClick(() => { + if (item.url !== '') { + this.popupState = false; + if (this.showSideBar) { + this.showSideBar = false; + } + this.getUIContext().getRouter().pushUrl({ url: item.url }); + } else { + if (this.dialogController === undefined) { + this.dialogController = new CustomDialogController({ + builder: UpdateTimeDialog({ handleCancelDialog: this.cancelDialog }), + autoCancel: false, + customStyle: true + }); + } + this.showDialog = true; + this.popupState = false; + this.dialogController.open(); + } + }) + }, (item: MenuData, index: number) => JSON.stringify(item) + index) + } + .width(160) + .padding(15) + .backgroundColor(Color.White) + .borderRadius(Style.NORMAL_RADIUS) + } + .padding({ right: 12 }) + } + + build() { + Row() { + if (!this.showSideBar && this.curBp === 'lg') { + Image($r('app.media.icon_subarea')) + .id('iconSubarea') + .size({ width: 24, height: 24 }) + .objectFit(ImageFit.Contain) + .onClick(() => { + this.showSideBar = !this.showSideBar; + }) + } + Text(this.titleText[this.swiperIndex]) + .fontSize(20) + .fontColor(Color.White) + .textAlign(TextAlign.Center) + .margin({ left: (!this.showSideBar && this.curBp === 'lg') ? 0 : 25 }) + .layoutWeight(1) + + Image($r('app.media.icon_more')) + .id('menuPopup') + .size({ width: 24, height: 24 }) + .objectFit(ImageFit.Fill) + .bindPopup(this.popupState, { + builder: this.popupBuilder, + placement: Placement.BottomLeft, + maskColor: 0x33000000, + popupColor: '#00000000', + enableArrow: false, + onStateChange: (e) => { + if (!e.isVisible) { + this.popupState = false; + } + } + }) + .onClick(() => { + this.popupState = !this.popupState; + }) + } + .width('100%') + .height('100%') + .padding({ left: Style.NORMAL_PADDING, right: Style.NORMAL_PADDING }) + } + + cancelDialog = () => { + this.dialogController?.close(); + this.showDialog = false; + } + + curBpChange() { + if (this.showDialog) { + this.dialogController?.close(); + this.dialogController = new CustomDialogController({ + builder: UpdateTimeDialog({ handleCancelDialog: this.cancelDialog }), + autoCancel: false, + customStyle: true + }); + this.dialogController.open(); + } + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/LifeIndex.ets b/Weather/product/default/src/main/ets/pages/LifeIndex.ets new file mode 100644 index 0000000000000000000000000000000000000000..bcc78117a527df19065941c0b99b77a6634de786 --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/LifeIndex.ets @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025 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 { getLifeData, MyDataSource, SuitData, Style } from 'common'; + +@Preview +@Component +export default struct LifeIndex { + lifeData: SuitData[] = getLifeData(0); + lifeDataResource: MyDataSource = new MyDataSource(this.lifeData); + + build() { + Grid() { + LazyForEach(this.lifeDataResource, (item: SuitData, index: number) => { + GridItem() { + Column() { + Image(item.src) + .width(24) + .height(24) + .objectFit(ImageFit.Contain) + Text(item.value) + .fontSize(14) + .fontColor(Color.White) + .margin({ top: 8 }) + Text(item.desc) + .fontSize(12) + .fontColor('#99FFFFFF') + .margin({ top: 2 }) + } + } + }, (item: SuitData, index: number) => JSON.stringify(item) + index) + } + .height(Style.CARD_HEIGHT) + .columnsTemplate('1fr 1fr 1fr 1fr') + .rowsTemplate('1fr 1fr') + .backgroundColor(Style.CARD_BACKGROUND_COLOR) + .borderRadius(Style.NORMAL_RADIUS) + } + + aboutToAppear() { + this.lifeDataResource.dataArray = this.lifeData; + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/MultidayWeather.ets b/Weather/product/default/src/main/ets/pages/MultidayWeather.ets new file mode 100644 index 0000000000000000000000000000000000000000..be2cceb0ea41b8c7b5b8075df178428a0b504fc4 --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/MultidayWeather.ets @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025 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 { getWeekWeatherData, MyDataSource, WeekWeather, Style } from 'common'; + +@Preview +@Component +export default struct MultidayWeather { + weekData: WeekWeather[] = getWeekWeatherData(0); + @State weekDataResource: MyDataSource = new MyDataSource(this.weekData); + + build() { + List() { + LazyForEach(this.weekDataResource, (item: WeekWeather, index: number) => { + ListItem() { + DayWeatherItem({ weatherInfo: item, index: index }) + .opacity(index === 0 ? 0.6 : 1) + .width(Style.WEATHER_ITEM_WIDTH) + .padding({ top: 16, bottom: 13 }) + } + }, (item: WeekWeather, index: number) => JSON.stringify(item) + index) + } + .width('100%') + .height(Style.CARD_HEIGHT) + .listDirection(Axis.Horizontal) + .borderRadius(Style.NORMAL_RADIUS) + .backgroundColor(Style.CARD_BACKGROUND_COLOR) + } + + aboutToAppear() { + this.weekDataResource.dataArray = this.weekData; + } +} + +@Component +struct DayWeatherItem { + index: number = 0; + weatherInfo?: WeekWeather; + + build() { + Column() { + Text(this.index === 0 ? $r('app.string.yestoday') : + this.index === 1 ? $r('app.string.today') : this.weatherInfo?.week) + .fontSize(12) + .fontColor(Color.White) + Text(this.weatherInfo?.date) + .fontSize(10) + .fontColor(Color.White) + .margin({ top: 4 }) + Row() { + Image(this.weatherInfo?.icon) + .width(28) + .height(28) + .objectFit(ImageFit.Contain) + } + .margin({ top: 8 }) + .justifyContent(FlexAlign.Center) + + Text(this.weatherInfo?.weather) + .fontSize(12) + .fontColor(Color.White) + .margin({ top: 8 }) + Text(`${this.weatherInfo?.min}°-${this.weatherInfo?.max}°`) + .fontSize(14) + .fontColor(Color.White) + .margin({ top: 16 }) + Text(this.weatherInfo?.airLevel) + .fontSize(10) + .fontColor(Color.White) + .margin({ top: 19 }) + .backgroundColor('#24FFFFFF') + .width(26) + .height(16) + .textAlign(TextAlign.Center) + .borderRadius(11) + } + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/SideContent.ets b/Weather/product/default/src/main/ets/pages/SideContent.ets new file mode 100644 index 0000000000000000000000000000000000000000..2300688bf3600fb9d5cb32de9a67e5f3b967662b --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/SideContent.ets @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2025 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 { City, getSideBg, MyDataSource, Style } from 'common'; + +@Component +export default struct SideContent { + @StorageLink('cityList') @Watch('cityListChange') cities: Array = []; + @StorageLink('swiperIndex') swiperIndex: number = 0; + @Link showSideBar: boolean; + cityList: MyDataSource = new MyDataSource(this.cities); + + @Builder + header() { + Row() { + Blank() + Image($r('app.media.icon_subarea')) + .id('cancelSubarea') + .size({ width: 24, height: 24 }) + .objectFit(ImageFit.Contain) + .onClick(() => { + this.showSideBar = !this.showSideBar; + }) + } + .width('100%') + + Text($r('app.string.weather')) + .fontColor(Color.White) + .fontSize(30) + .fontWeight(FontWeight.Medium) + .width('100%') + Search({ placeholder: '搜索城市(中文/拼音)', icon: '/common/images/icon_search.svg' }) + .placeholderFont({ size: 16 }) + .placeholderColor('#60FFFFFF') + .width('100%') + .backgroundColor('#26FFFFFF') + .margin({ top: 4 }) + .borderRadius(45) + } + + build() { + Column({ space: Style.NORMAL_SPACE }) { + this.header() + List({ space: 12 }) { + LazyForEach(this.cityList, (item: City, index: number) => { + ListItem() { + CityItem({ cityInfo: item, index: index }) + } + .id('sliderCity' + index) + .onClick(() => { + this.swiperIndex = index; + AppStorage.setOrCreate('swiperIndex', index); + }) + }, (item: City, index: number) => JSON.stringify(item) + index) + } + .margin({ top: 8 }) + .width('100%') + .layoutWeight(1) + } + .width('100%') + .height('100%') + .padding(Style.NORMAL_PADDING) + .backgroundColor('#0D000000') + } + + cityListChange() { + this.cityList.dataArray = this.cities; + this.cityList.notifyDataReload(); + } +} + +@Component +struct CityItem { + @StorageLink('swiperIndex') swiperIndex: number = 0; + cityInfo?: City; + index: number = 0; + + build() { + Row() { + Text(this.cityInfo?.name) + .fontColor(Color.White) + .fontSize(24) + if (this.index === 0) { + Image($r('app.media.icon_location')) + .size({ width: 16, height: 16 }) + .objectFit(ImageFit.Contain) + } + Blank() + Column() { + Row() { + Text(this.cityInfo?.temp) + .fontColor(Color.White) + .fontWeight(Style.BIG_FONT_WEIGHT) + .fontSize(54) + Text($r('app.string.du')) + .fontColor(Color.White) + .fontSize(20) + .margin({ bottom: 28 }) + } + + Text(this.cityInfo?.weather) + .fontColor(Color.White) + .fontSize(14) + } + } + .width('100%') + .height(100) + .alignItems(VerticalAlign.Center) + .padding(Style.NORMAL_PADDING) + .border({ + radius: Style.NORMAL_RADIUS, + width: 1, + color: this.swiperIndex === this.index ? '#BBFFFFFF' : '#116ACD' + }) + .alignItems(VerticalAlign.Center) + .backgroundImageSize(ImageSize.Cover) + .backgroundImage(getSideBg(this.cityInfo!.weather)) + } +} diff --git a/Weather/product/default/src/main/ets/pages/SunCanvas.ets b/Weather/product/default/src/main/ets/pages/SunCanvas.ets new file mode 100644 index 0000000000000000000000000000000000000000..881bda7089af10704f94c2c40a5b637a7e05a543 --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/SunCanvas.ets @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 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 { Style } from 'common'; +import { initMoon, initSun } from '../feature/SunCanvasFeature'; + +@Preview +@Component +export default struct SunCanvas { + sunImg: ImageBitmap = new ImageBitmap('/common/images/sun.png'); + moonImg: ImageBitmap = new ImageBitmap('/common/images/moon.png'); + iconMoon: ImageBitmap = new ImageBitmap('/common/images/icon_moon.svg'); + settings: RenderingContextSettings = new RenderingContextSettings(true); + context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); + + build() { + Row() { + Canvas(this.context) + .height('95%') + .aspectRatio(1.8) + .onReady(() => { + this.context.clearRect(0, 0, this.context.width, this.context.height); + initSun(this.context, this.sunImg); + initMoon(this.context, this.moonImg, this.iconMoon); + }) + } + .width('100%') + .height(Style.CARD_HEIGHT) + .justifyContent(FlexAlign.Center) + .backgroundColor(Style.CARD_BACKGROUND_COLOR) + .borderRadius(Style.NORMAL_RADIUS) + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/ets/pages/UpdateTimeDialog.ets b/Weather/product/default/src/main/ets/pages/UpdateTimeDialog.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f6d3488e27849749d09cb1df0b21abdaf361562 --- /dev/null +++ b/Weather/product/default/src/main/ets/pages/UpdateTimeDialog.ets @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2025 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 { getUpdateTimes, Style } from 'common'; + +@Preview +@CustomDialog +export default struct UpdateTimeDialog { + @StorageLink('curBp') curBp: string = 'md'; + controller: CustomDialogController; + updateTimes: string[] = getUpdateTimes(); + handleCancelDialog: () => void = () => { + }; + + build() { + GridRow({ + columns: { sm: 4, md: 8, lg: 12 }, + gutter: { x: Style.GRID_GUTTER, y: Style.GRID_GUTTER }, + breakpoints: { reference: BreakpointsReference.WindowSize } + }) { + GridCol({ span: 4, offset: { sm: 0, md: 2, lg: 4 } }) { + Row() { + Column() { + Text($r('app.string.update_time')) + .width('100%') + .fontSize(20) + .fontWeight(FontWeight.Medium) + .margin({ top: 14 }) + List() { + ForEach(this.updateTimes, (item: string, index: number) => { + ListItem() { + UpdateTimeItem({ index: index, updateTime: item }) + } + }, (item: string, index: number) => JSON.stringify(item) + index) + } + .lanes(this.curBp === 'lg' ? 2 : 1) + .divider({ strokeWidth: 1 }) + .margin({ top: Style.TIME_LIST_MARGIN }) + .width('100%') + .height(this.calcListHeight()) + + Text($r('app.string.cancel')) + .width('100%') + .fontSize(16) + .fontColor('#0A59F7') + .textAlign(TextAlign.Center) + .fontWeight(FontWeight.Medium) + .margin({ top: 9, bottom: 25 }) + .onClick(() => { + this.handleCancelDialog(); + }) + } + .padding({ left: Style.DIALOG_PADDING, right: Style.DIALOG_PADDING }) + .backgroundColor(Color.White) + .borderRadius(24) + } + .height('100%') + .alignItems(this.curBp === 'sm' ? VerticalAlign.Bottom : VerticalAlign.Center) + .padding({ + left: Style.DIALOG_PADDING_OUT, + right: Style.DIALOG_PADDING_OUT, + bottom: this.curBp === 'sm' ? Style.DIALOG_PADDING_OUT : 0 + }) + } + } + } + + calcListHeight() { + if (this.curBp === 'lg') { + return Style.TIME_LIST_HEIGHT * this.updateTimes.length / 2 + Style.TIME_LIST_MARGIN; + } else { + return Style.TIME_LIST_HEIGHT * this.updateTimes.length + Style.TIME_LIST_MARGIN; + } + } +} + +@Component +struct UpdateTimeItem { + index: number = 0; + updateTime: string = ''; + @StorageLink('curBp') curBp: string = 'md'; + + build() { + Row() { + Text(this.updateTime) + .fontSize(16) + Blank() + Radio({ group: 'time', value: this.updateTime }) + .width(20) + .height(20) + } + .width('100%') + .height(Style.TIME_LIST_HEIGHT) + .padding(this.curBp === 'lg' ? (this.index % 2 === 0 ? { right: 10 } : { left: 10 }) : 0) + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/module.json5 b/Weather/product/default/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..9016250f45254a24e8a9f2c2ba5c25f3c37c8eee --- /dev/null +++ b/Weather/product/default/src/main/module.json5 @@ -0,0 +1,51 @@ +{ + "module": { + "name": "default", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "phone", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/AdaptiveCapabilities/entry/src/ohosTest/resources/base/element/color.json b/Weather/product/default/src/main/resources/base/element/color.json similarity index 100% rename from AdaptiveCapabilities/entry/src/ohosTest/resources/base/element/color.json rename to Weather/product/default/src/main/resources/base/element/color.json diff --git a/Weather/product/default/src/main/resources/base/element/float.json b/Weather/product/default/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6 --- /dev/null +++ b/Weather/product/default/src/main/resources/base/element/float.json @@ -0,0 +1,8 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + } + ] +} diff --git a/Weather/product/default/src/main/resources/base/element/string.json b/Weather/product/default/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..04e698f2275e7864fed564b1f3e3c9d0ebfdcdd1 --- /dev/null +++ b/Weather/product/default/src/main/resources/base/element/string.json @@ -0,0 +1,92 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "weather" + }, + { + "name": "EntryAbility_desc", + "value": "Multiple weather conditions" + }, + { + "name": "EntryAbility_label", + "value": "weather" + }, + { + "name": "midnight", + "value": "半夜" + }, + { + "name": "early_morning", + "value": "清晨" + }, + { + "name": "morning", + "value": "早上" + }, + { + "name": "yestoday", + "value": "昨天" + }, + { + "name": "today", + "value": "今天" + }, + { + "name": "air", + "value": "空气" + }, + { + "name": "air_quality", + "value": "污染指数" + }, + { + "name": "weather", + "value": "天气" + }, + { + "name": "china_weather", + "value": "中国天气" + }, + { + "name": "weather_version", + "value": "天气版本:11.1.0" + }, + { + "name": "weather_statement", + "value": "关于天气与隐私的声明" + }, + { + "name": "weather_copyright", + "value": "版权所有2020 OpenHarmony技术有限公司" + }, + { + "name": "du", + "value": "℃" + }, + { + "name": "manage_city", + "value": "管理城市" + }, + { + "name": "add_city", + "value": "添加城市" + }, + { + "name": "search_placeholder", + "value": "搜索城市(中文/拼音)" + }, + { + "name": "update_time", + "value": "更新时间" + }, + { + "name": "cancel", + "value": "取消" + }, + { + "name": "hot_city", + "value": "热门城市" + } + ] +} \ No newline at end of file diff --git a/Weather/product/default/src/main/resources/base/media/background.png b/Weather/product/default/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/Weather/product/default/src/main/resources/base/media/background.png differ diff --git a/Weather/product/default/src/main/resources/base/media/foreground.png b/Weather/product/default/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/Weather/product/default/src/main/resources/base/media/foreground.png differ diff --git a/AdaptiveCapabilities/entry/src/ohosTest/resources/base/media/icon.png b/Weather/product/default/src/main/resources/base/media/icon.png similarity index 100% rename from AdaptiveCapabilities/entry/src/ohosTest/resources/base/media/icon.png rename to Weather/product/default/src/main/resources/base/media/icon.png diff --git a/Weather/product/default/src/main/resources/base/media/icon_add.svg b/Weather/product/default/src/main/resources/base/media/icon_add.svg new file mode 100644 index 0000000000000000000000000000000000000000..c851dfdf09ea66d2b8ba2d7e86fb10ce882a00cc --- /dev/null +++ b/Weather/product/default/src/main/resources/base/media/icon_add.svg @@ -0,0 +1,13 @@ + + + icon_add + + + + + + + + + + \ No newline at end of file diff --git a/Weather/product/default/src/main/resources/base/media/icon_back.png b/Weather/product/default/src/main/resources/base/media/icon_back.png new file mode 100644 index 0000000000000000000000000000000000000000..fd6fb7b10f96aafcbc7c63deea779464a03ca733 Binary files /dev/null and b/Weather/product/default/src/main/resources/base/media/icon_back.png differ diff --git a/Weather/product/default/src/main/resources/base/media/icon_china_weather.svg b/Weather/product/default/src/main/resources/base/media/icon_china_weather.svg new file mode 100644 index 0000000000000000000000000000000000000000..abc6a8b42293aa33570676c3e6c3edc9f7d615ec --- /dev/null +++ b/Weather/product/default/src/main/resources/base/media/icon_china_weather.svg @@ -0,0 +1,29 @@ + + + icon_Chinaweather + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Weather/product/default/src/main/resources/base/media/icon_location.svg b/Weather/product/default/src/main/resources/base/media/icon_location.svg new file mode 100644 index 0000000000000000000000000000000000000000..8c6e21fdc8163bf47d60ae887389597e53a9130b --- /dev/null +++ b/Weather/product/default/src/main/resources/base/media/icon_location.svg @@ -0,0 +1,13 @@ + + + icon_location + + + + + + + + + + \ No newline at end of file diff --git a/Weather/product/default/src/main/resources/base/media/icon_message.svg b/Weather/product/default/src/main/resources/base/media/icon_message.svg new file mode 100644 index 0000000000000000000000000000000000000000..2ebab02900fa386001aedf23c8881c53611613b6 --- /dev/null +++ b/Weather/product/default/src/main/resources/base/media/icon_message.svg @@ -0,0 +1,10 @@ + + + icon_message + + + + + + + \ No newline at end of file diff --git a/Weather/product/default/src/main/resources/base/media/icon_moon.svg b/Weather/product/default/src/main/resources/base/media/icon_moon.svg new file mode 100644 index 0000000000000000000000000000000000000000..01b6b8114877b11093a9d2268cb7f678c283b309 --- /dev/null +++ b/Weather/product/default/src/main/resources/base/media/icon_moon.svg @@ -0,0 +1,7 @@ + + + icon_moon + + + + \ No newline at end of file diff --git a/Weather/product/default/src/main/resources/base/media/icon_more.svg b/Weather/product/default/src/main/resources/base/media/icon_more.svg new file mode 100644 index 0000000000000000000000000000000000000000..c022902bc75dcbdc36a9726dd18cfde75ab77a22 --- /dev/null +++ b/Weather/product/default/src/main/resources/base/media/icon_more.svg @@ -0,0 +1,10 @@ + + + icon_more + + + + + + + \ No newline at end of file diff --git a/Weather/product/default/src/main/resources/base/media/icon_search.svg b/Weather/product/default/src/main/resources/base/media/icon_search.svg new file mode 100644 index 0000000000000000000000000000000000000000..eee9b524c12507273cdb04ca879e985819e4064b --- /dev/null +++ b/Weather/product/default/src/main/resources/base/media/icon_search.svg @@ -0,0 +1,13 @@ + + + icon_search + + + + + + + + + + \ No newline at end of file diff --git a/Weather/product/default/src/main/resources/base/media/icon_side.png b/Weather/product/default/src/main/resources/base/media/icon_side.png new file mode 100644 index 0000000000000000000000000000000000000000..154d2b7ae08867af5f6d78e29aa362170ac24b73 Binary files /dev/null and b/Weather/product/default/src/main/resources/base/media/icon_side.png differ diff --git a/Weather/product/default/src/main/resources/base/media/icon_subarea.svg b/Weather/product/default/src/main/resources/base/media/icon_subarea.svg new file mode 100644 index 0000000000000000000000000000000000000000..91ef8b43222d75d3b204d7a82814fc520938dd58 --- /dev/null +++ b/Weather/product/default/src/main/resources/base/media/icon_subarea.svg @@ -0,0 +1,10 @@ + + + icon_subarea + + + + + + + \ No newline at end of file diff --git a/Weather/product/default/src/main/resources/base/media/layered_image.json b/Weather/product/default/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/Weather/product/default/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/Weather/product/default/src/main/resources/base/media/startIcon.png b/Weather/product/default/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/Weather/product/default/src/main/resources/base/media/startIcon.png differ diff --git a/Weather/product/default/src/main/resources/base/profile/backup_config.json b/Weather/product/default/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/Weather/product/default/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/Weather/product/default/src/main/resources/base/profile/main_pages.json b/Weather/product/default/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..d8a324c61ee13a0908160ef5b2c8d23be0a244cc --- /dev/null +++ b/Weather/product/default/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,7 @@ +{ + "src": [ + "pages/Home", + "pages/CityList", + "pages/AddCity" + ] +} diff --git a/Weather/screenshots/devices/zh/add_city.png b/Weather/screenshots/devices/zh/add_city.png new file mode 100644 index 0000000000000000000000000000000000000000..1beb0c5064a9765c30a328dd2731a9ff9dedd03b Binary files /dev/null and b/Weather/screenshots/devices/zh/add_city.png differ diff --git a/Weather/screenshots/devices/zh/city.png b/Weather/screenshots/devices/zh/city.png new file mode 100644 index 0000000000000000000000000000000000000000..ef7c5ab5c18ed7030334d11bd9e31777720f5b96 Binary files /dev/null and b/Weather/screenshots/devices/zh/city.png differ diff --git a/Weather/screenshots/devices/zh/home.png b/Weather/screenshots/devices/zh/home.png new file mode 100644 index 0000000000000000000000000000000000000000..17c6fe1552d4af75823b54f8b0ca033631b96c4b Binary files /dev/null and b/Weather/screenshots/devices/zh/home.png differ