diff --git a/entry/obfuscation-rules.txt b/entry/obfuscation-rules.txt index 985b2aeb7658286b17bd26eab8f217c3fe75ea8b..a1dfa0bd175984dc49e641436aa67b1de1b8abeb 100644 --- a/entry/obfuscation-rules.txt +++ b/entry/obfuscation-rules.txt @@ -15,4 +15,8 @@ # 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 \ No newline at end of file +# -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/entry/src/main/ets/common/constants/CommonConstants.ets b/entry/src/main/ets/common/constants/CommonConstants.ets index c5894a3f3e6990cd8ee487791286e519d3bce516..4c8dfb757834a8a2287d07bd60ee4d8a3aa0444d 100644 --- a/entry/src/main/ets/common/constants/CommonConstants.ets +++ b/entry/src/main/ets/common/constants/CommonConstants.ets @@ -82,4 +82,19 @@ export class CommonConstants { * Height the percentage of the 100. */ static readonly FULL_HEIGHT: string = '100%'; + + /** + * Breakpoint sm. + */ + static readonly BREAK_POINT_SM: string = 'sm'; + + /** + * Breakpoint md. + */ + static readonly BREAK_POINT_MD: string = 'md'; + + /** + * Breakpoint lg. + */ + static readonly BREAK_POINT_LG: string = 'lg'; } \ No newline at end of file diff --git a/entry/src/main/ets/common/utils/Utils.ets b/entry/src/main/ets/common/utils/Utils.ets new file mode 100644 index 0000000000000000000000000000000000000000..820d7bb1ea99bc93ecd4abf9b78b939835b3f5cc --- /dev/null +++ b/entry/src/main/ets/common/utils/Utils.ets @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { CommonConstants } from "../constants/CommonConstants"; + +export class BreakpointType { + sm: T; + md: T; + lg: T; + + constructor(sm: T, md: T, lg: T) { + this.sm = sm; + this.md = md; + this.lg = lg; + } + + getValue(currentBreakpoint: string): T { + if (currentBreakpoint === CommonConstants.BREAK_POINT_MD) { + return this.md; + } + if (currentBreakpoint === CommonConstants.BREAK_POINT_LG) { + return this.lg; + } else { + return this.sm; + } + } +} \ No newline at end of file diff --git a/entry/src/main/ets/entryability/EntryAbility.ets b/entry/src/main/ets/entryability/EntryAbility.ets index 034ae42c1bbdf8633d4defba894e83f3f4e1419b..579b04b4851dae2b6e3c8c8108303cd9374dbbd6 100644 --- a/entry/src/main/ets/entryability/EntryAbility.ets +++ b/entry/src/main/ets/entryability/EntryAbility.ets @@ -13,13 +13,45 @@ * limitations under the License. */ -import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { AbilityConstant, Configuration, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { display, window } from '@kit.ArkUI'; import { hilog } from '@kit.PerformanceAnalysisKit'; -import { window } from '@kit.ArkUI'; +import { BusinessError } from '@kit.BasicServicesKit'; +import { resourceManager } from '@kit.LocalizationKit'; export default class EntryAbility extends UIAbility { + private windowObj?: window.Window; + private curBp: string = ''; + + private updateBreakpoint(windowWidth: number): void { + let windowWidthVp = windowWidth / display.getDefaultDisplaySync().densityPixels; + let newBp: string = ''; + if (windowWidthVp < 600) { + newBp = 'sm'; + } else if (windowWidthVp < 840) { + newBp = 'md'; + } else { + newBp = 'lg'; + } + if (this.curBp !== newBp) { + this.curBp = newBp; + AppStorage.setOrCreate('currentBreakpoint', this.curBp); + } + } + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + AppStorage.setOrCreate('systemColorMode', this.context.config.colorMode); + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + } + + onConfigurationUpdate(newConfig: Configuration): void { + let newColorMode: ConfigurationConstant.ColorMode = + newConfig.colorMode || ConfigurationConstant.ColorMode.COLOR_MODE_DARK; + let currentColorMode = AppStorage.get('systemColorMode'); + if (newColorMode !== currentColorMode) { + AppStorage.setOrCreate('systemColorMode', newColorMode); + } } onDestroy(): void { @@ -27,16 +59,39 @@ export default class EntryAbility extends UIAbility { } onWindowStageCreate(windowStage: window.WindowStage): void { + windowStage.getMainWindow().then((windowObj: window.Window) => { + let type = window.AvoidAreaType.TYPE_NAVIGATION_INDICATOR; + let avoidArea = windowObj.getWindowAvoidArea(type); + let bottomRectHeight = avoidArea.bottomRect.height; + AppStorage.setOrCreate('bottomRectHeight', bottomRectHeight); + type = window.AvoidAreaType.TYPE_SYSTEM; + avoidArea = windowObj.getWindowAvoidArea(type); + let topRectHeight = avoidArea.topRect.height; + AppStorage.setOrCreate('topRectHeight', topRectHeight); + this.windowObj = windowObj; + this.updateBreakpoint(windowObj.getWindowProperties().windowRect.width); + windowObj.on('windowSizeChange', (windowSize) => { + this.updateBreakpoint(windowSize.width); + }) + }); // Main window is created, set main page for this ability hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); - + let context = this.context; + let resourceManager: resourceManager.ResourceManager = context.resourceManager; + AppStorage.setOrCreate('resourceManager', resourceManager); windowStage.loadContent('pages/Index', (err, data) => { 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. Data: %{public}s', JSON.stringify(data) ?? ''); - windowStage.getMainWindowSync().setWindowBackgroundColor('#F1F3F5'); + let windowClass: window.Window = windowStage.getMainWindowSync(); + let isLayoutFullScreen = true; + windowClass.setWindowLayoutFullScreen(isLayoutFullScreen).then(() => { + console.info('Succeeded in setting the window layout to full-screen mode.'); + }).catch((err: BusinessError) => { + console.error('Failed to set the window layout to full-screen mode. Cause:' + JSON.stringify(err)); + }); }); } diff --git a/entry/src/main/ets/pages/Index.ets b/entry/src/main/ets/pages/Index.ets index f69ab3e9f72c93aa97fad26dd542ed4cd3b71810..bd5e7afc61df3021a8c93cc0ff552268f5f339c0 100644 --- a/entry/src/main/ets/pages/Index.ets +++ b/entry/src/main/ets/pages/Index.ets @@ -15,73 +15,103 @@ import { listArr } from '../viewmodel/InitData'; import { CommonConstants } from '../common/constants/CommonConstants'; +import { BreakpointType } from '../common/utils/Utils'; +import { + ItemRestriction, + SegmentButton, + SegmentButtonOptions, + SegmentButtonTextItem +} from '@ohos.arkui.advanced.SegmentButton'; @Entry @Component struct NestedCeiling { + @State @Watch('onSegmentButtonChange') tabSelectedIndexes: number[] = [0]; @State currentIndex: number = 0; + @State tabOptions: SegmentButtonOptions = SegmentButtonOptions.tab({ + buttons: [{ text: $r('app.string.Promotional') }, + { text: $r('app.string.Travel') }] as ItemRestriction, + fontSize: $r('sys.float.Body_M'), + selectedFontSize: $r('sys.float.Body_M'), + fontColor: $r('sys.color.font_secondary'), + selectedFontColor: $r('sys.color.font_primary'), + backgroundColor: $r('sys.color.comp_background_tertiary'), + selectedBackgroundColor: $r('sys.color.ohos_id_color_foreground_contrary_disable'), + textPadding: { + top: 8, + bottom: 8, + right: 16, + left: 16 + }, + }) + @StorageLink('currentBreakpoint') curBp: string = CommonConstants.BREAK_POINT_SM; + @StorageProp('topRectHeight') + topRectHeight: number = 0; private scrollerForScroll: Scroller = new Scroller(); private scrollerForList: Scroller = new Scroller(); + onSegmentButtonChange() { + this.currentIndex = this.tabSelectedIndexes[0]; + } + @Builder tabBuilder(index: number, name: ResourceStr) { Column() { Text(name) - .fontColor(this.currentIndex === index ? $r('app.color.active_font_color') : $r('app.color.font_color')) + .fontColor(this.currentIndex === index ? $r('sys.color.font_on_primary') : $r('sys.color.brand')) .fontSize($r('app.float.middle_font_size')) - .fontWeight(this.currentIndex === index ? CommonConstants.FONT_WEIGHT_FIVE : CommonConstants.FONT_WEIGHT_FOUR) - .lineHeight($r('app.float.title_line_height')) - .margin({ - top: $r('app.float.title_margin_top'), - bottom: $r('app.float.title_margin_bottom') - }) - Divider() - .strokeWidth(CommonConstants.STROKE_WIDTH) - .width($r('app.float.divider_width')) - .color($r('app.color.active_font_color')) - .opacity(this.currentIndex === index ? CommonConstants.FULL_OPACITY : CommonConstants.ZERO_OPACITY) } + .borderRadius($r('app.float.button_border_radius')) + .justifyContent(FlexAlign.Center) + .height($r('app.float.button_height')) + .width($r('app.float.button_width')) + .backgroundColor(this.currentIndex === index ? $r('sys.color.brand') : $r('sys.color.comp_background_tertiary')) } @Builder listBuilder(listName: ResourceStr, tabName: ResourceStr, index: number) { - TabContent() { - List({ space: CommonConstants.LIST_SPACE, scroller: this.scrollerForList }) { - ForEach(listArr, (item: string) => { - ListItem() { - Row() { - Text(listName) - .fontSize($r('app.float.middle_font_size')) - .fontWeight(CommonConstants.FONT_WEIGHT_FIVE) - Text(item) - .fontSize($r('app.float.middle_font_size')) - .fontWeight(CommonConstants.FONT_WEIGHT_FIVE) - } - .padding({ left: $r('app.float.list_item_padding') }) - .backgroundColor(Color.White) - .width(CommonConstants.FULL_WIDTH) - .height(CommonConstants.FULL_HEIGHT) - .borderRadius($r('app.float.list_item_radius')) - + List({ scroller: this.scrollerForList }) { + ForEach(listArr, (item: string, index: number) => { + ListItem() { + Row() { + Text(listName) + .fontSize($r('app.float.middle_font_size')) + .fontColor($r('sys.color.font_primary')) + .fontWeight(CommonConstants.FONT_WEIGHT_FIVE) + Text(item) + .fontSize($r('app.float.middle_font_size')) + .fontWeight(CommonConstants.FONT_WEIGHT_FIVE) + .fontColor($r('sys.color.font_primary')) } + .justifyContent(FlexAlign.Center) + .borderColor($r('sys.color.comp_divider')) + .borderWidth({ bottom: 0.5 }) + .backgroundColor($r('sys.color.comp_background_primary')) .width(CommonConstants.FULL_WIDTH) - .height($r('app.float.list_item_height')) - }, (item: string) => JSON.stringify(item)) - } - .padding({ - left: $r('app.float.list_padding'), - right: $r('app.float.list_padding') - }) - .width(CommonConstants.FULL_WIDTH) - .height(CommonConstants.FULL_HEIGHT) - .edgeEffect(EdgeEffect.None) - .scrollBar(BarState.Off) - .nestedScroll({ - scrollForward: NestedScrollMode.PARENT_FIRST, - scrollBackward: NestedScrollMode.SELF_FIRST - }) + .height(CommonConstants.FULL_HEIGHT) + } + .borderRadius({ + bottomLeft: this.curBp === 'sm' ? ((index === listArr.length - 1) ? $r('app.float.list_item_radius') : 0) : + ((index === listArr.length - 2) ? $r('app.float.list_item_radius') : 0), + bottomRight: this.curBp === 'sm' ? ((index === listArr.length - 1) ? $r('app.float.list_item_radius') : 0) : + ((index === listArr.length - 1) ? $r('app.float.list_item_radius') : 0) + }) + .backgroundColor($r('sys.color.comp_background_primary')) + .padding({ left: $r('app.float.list_item_padding'), right: $r('app.float.list_item_padding') }) + .width(CommonConstants.FULL_WIDTH) + .height($r('app.float.list_item_height')) + }, (item: string) => JSON.stringify(item)) } - .tabBar(this.tabBuilder(index, tabName)) + .borderRadius($r('app.float.list_item_radius')) + .lanes(new BreakpointType(1, 2, 2).getValue(this.curBp)) + .width(CommonConstants.FULL_WIDTH) + .height(CommonConstants.FULL_HEIGHT) + .edgeEffect(EdgeEffect.None) + .scrollBar(BarState.Off) + .nestedScroll({ + scrollForward: NestedScrollMode.PARENT_FIRST, + scrollBackward: NestedScrollMode.SELF_FIRST + }) } build() { @@ -92,41 +122,38 @@ struct NestedCeiling { .height($r('app.float.list_item_height')) .textAlign(TextAlign.Start) .width(CommonConstants.FULL_WIDTH) - .padding({ - left: $r('app.float.discover_left_padding'), + .fontColor($r('sys.color.font_primary')) + .margin({ bottom: $r('app.float.discover_bottom_padding'), - top: $r('app.float.discover_top_padding') + top: $r('sys.float.padding_level32') }) - Stack({ alignContent: Alignment.Top }) { - Scroll(this.scrollerForScroll) { - Column() { - Image($r("app.media.banner")) - .width(CommonConstants.FULL_WIDTH) - .height($r('app.float.image_height')) - .borderRadius($r('app.float.list_item_radius')) - .padding({ - left: $r('app.float.list_item_padding'), - right: $r('app.float.list_item_padding') - }) - Tabs() { - this.listBuilder($r('app.string.goods'), $r('app.string.Promotional'), 0) - this.listBuilder($r('app.string.Itinerary'), $r('app.string.Travel'), 1) - } - .barWidth($r('app.float.bar_width')) - .onAnimationStart((_index: number, targetIndex: number, _event: TabsAnimationEvent) => { - this.currentIndex = targetIndex; - }) + + Scroll(this.scrollerForScroll) { + Column() { + SegmentButton({ options: this.tabOptions, selectedIndexes: this.tabSelectedIndexes }) + .width(this.curBp === 'sm' ? '100%' : 448) + .margin({ bottom: $r('sys.float.padding_level6') }) + if (this.currentIndex === 0) { + this.listBuilder($r('app.string.goods'), $r('app.string.Promotional'), 0) + } else { + this.listBuilder($r('app.string.Itinerary'), $r('app.string.Travel'), 1) } } - .scrollBar(BarState.Off) - .width(CommonConstants.FULL_WIDTH) - .height(CommonConstants.FULL_HEIGHT) } + .height(new BreakpointType('210%', '120%', '120%').getValue(this.curBp)) + .scrollBar(BarState.Off) .width(CommonConstants.FULL_WIDTH) - .height(CommonConstants.STACK_HEIGHT) } + .padding({ + left: new BreakpointType($r('sys.float.padding_level8'), $r('sys.float.padding_level12'), + $r('sys.float.padding_level16')).getValue(this.curBp), + right: new BreakpointType($r('sys.float.padding_level8'), $r('sys.float.padding_level12'), + $r('sys.float.padding_level16')).getValue(this.curBp), + top: px2vp(this.topRectHeight) + }) + .width(CommonConstants.FULL_WIDTH) .height(CommonConstants.FULL_HEIGHT) - .backgroundColor($r('app.color.start_window_background')) + .backgroundColor($r('sys.color.background_secondary')) } } \ No newline at end of file diff --git a/entry/src/main/ets/viewmodel/InitData.ets b/entry/src/main/ets/viewmodel/InitData.ets index fc218ea50b259b67106bb6fb2e9df76d3f2bdd44..cf044492379cb9351ef02a7db2dfdc07b815d448 100644 --- a/entry/src/main/ets/viewmodel/InitData.ets +++ b/entry/src/main/ets/viewmodel/InitData.ets @@ -16,4 +16,6 @@ /** * List data */ -export const listArr: string[] = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11']; \ No newline at end of file +export const listArr: string[] = + ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', + '22', '23', '24']; \ No newline at end of file diff --git a/entry/src/main/resources/base/element/float.json b/entry/src/main/resources/base/element/float.json index 3fec9722c880abb2e44e8db2d1ec127c73695c97..eb404fece5cf879a76ff9ddf8dc9721ba160d500 100644 --- a/entry/src/main/resources/base/element/float.json +++ b/entry/src/main/resources/base/element/float.json @@ -2,11 +2,23 @@ "float": [ { "name": "middle_font_size", - "value": "16fp" + "value": "14fp" + }, + { + "name": "button_border_radius", + "value": "21fp" + }, + { + "name": "button_height", + "value": "36fp" + }, + { + "name": "button_width", + "value": "84fp" }, { "name": "title_line_height", - "value": "22vp" + "value": "36vp" }, { "name": "title_margin_top", @@ -22,7 +34,7 @@ }, { "name": "list_item_radius", - "value": "24vp" + "value": "16vp" }, { "name": "list_item_padding", @@ -50,7 +62,7 @@ }, { "name": "discover_bottom_padding", - "value": "8vp" + "value": "16vp" }, { "name": "image_width", @@ -61,8 +73,16 @@ "value": "188vp" }, { - "name": "bar_width", + "name": "bar_width_sm", "value": "290vp" + }, + { + "name": "bar_width_md", + "value": "500vp" + }, + { + "name": "bar_width_lg", + "value": "700vp" } ] } \ No newline at end of file diff --git a/entry/src/main/resources/base/element/string.json b/entry/src/main/resources/base/element/string.json index cc16f2f10980f300e73346e67329549acdf82a3b..e64f6259e1b2a6801fffa820f8b2fb6ad0b81c44 100644 --- a/entry/src/main/resources/base/element/string.json +++ b/entry/src/main/resources/base/element/string.json @@ -14,7 +14,7 @@ }, { "name": "title", - "value": "发现" + "value": "Scroll组件嵌套滑动" }, { "name": "Promotional", diff --git a/entry/src/main/resources/en_US/element/string.json b/entry/src/main/resources/en_US/element/string.json index a63e5ac38fe4bc96c69eff93a163d9e9421d939e..cf462b72a09320f8b68af2f622ad8e8be4daf8a3 100644 --- a/entry/src/main/resources/en_US/element/string.json +++ b/entry/src/main/resources/en_US/element/string.json @@ -14,7 +14,7 @@ }, { "name": "title", - "value": "Discover" + "value": "Nested scrolling of the Scroll component" }, { "name": "Promotional", diff --git a/entry/src/main/resources/zh_CN/element/string.json b/entry/src/main/resources/zh_CN/element/string.json index cc16f2f10980f300e73346e67329549acdf82a3b..e64f6259e1b2a6801fffa820f8b2fb6ad0b81c44 100644 --- a/entry/src/main/resources/zh_CN/element/string.json +++ b/entry/src/main/resources/zh_CN/element/string.json @@ -14,7 +14,7 @@ }, { "name": "title", - "value": "发现" + "value": "Scroll组件嵌套滑动" }, { "name": "Promotional",