diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000000000000000000000000000000000000..51101a29ce746e01518ce665577de05690470f5a --- /dev/null +++ b/README.en.md @@ -0,0 +1,48 @@ +# Long Video + +### Introduction + +This codelab implements a short video app based on the adaptive layout and responsive layout, achieving one-time development for multi-device deployment. It uses the three-layer project architecture for code reuse and tailors the pages to different device sizes such as mobile phones, foldable phones, tablets, and 2-in-1 devices. + +The figure shows the effect on the mobile phone: + +![](screenshots/device/phone_EN.png) + +The figure shows the effect on the foldable phone: + +![](screenshots/device/foldable_EN.JPG) + +The figure shows the effect on the tablet and 2-in-1 device: + +![](screenshots/device/tablet_EN.png) + +### Concepts + +- One-time development for multi-device deployment: You only need to develop and release one set of project code and then deploy it on multiple devices as demanded. This feature enables you to efficiently develop applications that are compatible with multiple devices while providing distributed user experiences for cross-device transferring, migration, and collaboration. +- Adaptive layout: When the size of an external container changes, elements can automatically change based on the relative relationship to adapt to the external container. Relative relationships include the proportion, fixed aspect ratio, and display priority. +- Responsive layout: When the size of an external container changes, elements can automatically change based on the breakpoints, grids, or specific features (such as the screen direction and window width and height) to adapt to the external container. +- GridRow: A container that is used in a grid layout, together with its child component **GridCol**. +- GridCol: A container that must be used as a child component of the **GridRow** container. +- Using the AVPlayer for audio playback: The AVPlayer can be used to play raw media assets in an end-to-end manner. + +### Permissions + +N/A. + +### How to Use + +1. Install and open an app on a mobile phone, foldable phone, or tablet. The responsive layout and adaptive layout are used to display different effects on the app pages over different devices. +2. Swipe up or down the home page content and swipe left or right banners and icon lists. +3. Touch and hold the first image in the recommended video area to preview the video. Right-click the recommended video area and a menu is displayed. Hover the mouse pointer over the recommended video area to zoom in the image. Pinch two fingers to zoom in or out the video area on a 2-in-1 device or foldable phone. +4. Switch to the community tab on the top to view the immersive design of the home page. Switch to the video tab on the top to view the innovative layout of the banner images on a 2-in-1 device. +5. Click the search box on the top to display the search page. Enter "Hua" in the search box and the intelligent prompt page is displayed. Click "Huawei launch event" in the intelligent prompts. The search result page is displayed. Click the Play button in the search result. The video details page is displayed. +6. By default, the video is played on the video details page. Click the video to play or pause it, and click or drag the progress bar to seek to the playback position. +7. When you swipe up on a phone or foldable phone, the related list is hidden, the video is zoomed out proportionally, and the comment area is swiped. When you swipe up on a 2-in-1 device, the video is zoomed out proportionally and the introduction area is swiped. Click the full-screen button in the video area to access the full-screen playback page. +8. Play a video in full-screen mode and click the Play/Pause button to play or pause the video. Click the episode selection button. The episode selection toolbar is displayed. + +### Constraints + +1. The sample app is supported only on Huawei phones running the standard system. +2. HarmonyOS: HarmonyOS NEXT Developer Beta 1 or later +3. DevEco Studio: DevEco Studio NEXT Developer Beta 1 or later +4. HarmonyOS SDK: HarmonyOS NEXT Developer Beta 1 SDK or later diff --git a/README.md b/README.md index dceee4676000691d41f9f4443ddb66b5d3a3c621..0b05a6e622828d7b42ba43efc0dbefb251b99ad6 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ ### 相关概念 -- 一次开发,多端部署:一套代码工程,一次开发上架,多端按需部署。支撑开发者快速高效的开发支持多种终端设备形态的应用,实现对不同设备兼容的同时,提供跨设备的流转、迁移和协同的分布式体验。 +- 一次开发,多端部署:一套代码工程,一次开发上架,多端按需部署。支撑开发者高效的开发支持多种终端设备形态的应用,实现对不同设备兼容的同时,提供跨设备的流转、迁移和协同的分布式体验。 - 自适应布局:当外部容器大小发生变化时,元素可以根据相对关系自动变化以适应外部容器变化的布局能力。相对关系如占比、固定宽高比、显示优先级等。 - 响应式布局:当外部容器大小发生变化时,元素可以根据断点、栅格或特定的特征(如屏幕方向、窗口宽高等)自动变化以适应外部容器变化的布局能力。 - GridRow:栅格容器组件,仅可以和栅格子组件(GridCol)在栅格布局场景中使用。 diff --git a/commons/base/src/main/ets/utils/AvPlayerUtil.ets b/commons/base/src/main/ets/utils/AvPlayerUtil.ets index 27f9347280b528070eb47a9a99365ea1fa7509e7..bbbe6f116d8cda1234cb4103aaa79979ab5ccc0c 100644 --- a/commons/base/src/main/ets/utils/AvPlayerUtil.ets +++ b/commons/base/src/main/ets/utils/AvPlayerUtil.ets @@ -191,6 +191,20 @@ export class AvPlayerUtil { } } + fastForward(): void { + if (this.avPlayer?.state === CommonConstants.AV_PLAYER_PLAYING_STATE || this.avPlayer?.state === + CommonConstants.AV_PLAYER_PAUSED_STATE) { + this.avPlayer.seek(this.avPlayer.currentTime + 5000); + } + } + + rewind(): void { + if (this.avPlayer?.state === CommonConstants.AV_PLAYER_PLAYING_STATE || this.avPlayer?.state === + CommonConstants.AV_PLAYER_PAUSED_STATE) { + this.avPlayer.seek(this.avPlayer.currentTime - 5000); + } + } + formatTime(duration: number): string { let totalSecond: number = Math.round(duration / CommonConstants.PROGRESS_THOUSAND); let hourNum: number = Math.floor(totalSecond / CommonConstants.SECOND_IN_HOUR); diff --git a/commons/base/src/main/ets/utils/WindowUtil.ets b/commons/base/src/main/ets/utils/WindowUtil.ets index 775149c6220a6d5efde57f761c33738e4916b390..98f46dd4f34f93d35c5870fc04626d777163873c 100644 --- a/commons/base/src/main/ets/utils/WindowUtil.ets +++ b/commons/base/src/main/ets/utils/WindowUtil.ets @@ -62,6 +62,18 @@ export class WindowUtil { this.mainWindowClass!.setWindowLayoutFullScreen(true); } + maximize(): void { + if (this.mainWindowClass!.getWindowStatus() === window.WindowStatusType.FLOATING) { + this.mainWindowClass!.maximize(); + } + } + + recover(): void { + if (this.mainWindowClass!.getWindowStatus() === window.WindowStatusType.FULL_SCREEN) { + this.mainWindowClass!.recover(); + } + } + getMainWindow(): window.Window | undefined { return this.mainWindowClass; } @@ -73,7 +85,7 @@ export class WindowUtil { updateWidthBp(): void { let mainWindow: window.WindowProperties = this.mainWindowClass!.getWindowProperties(); let windowWidth: number = mainWindow.windowRect.width; - let windowWidthVp = windowWidth / display.getDefaultDisplaySync().densityPixels; + let windowWidthVp = windowWidth / (display.getDefaultDisplaySync().densityDPI / 160); if (deviceInfo.deviceType === CommonConstants.DEVICE_TYPE) { windowWidthVp -= 2 * CommonConstants.WINDOW_FLOATING_MARGIN; } @@ -100,8 +112,8 @@ export class WindowUtil { let mainWindow: window.WindowProperties = this.mainWindowClass!.getWindowProperties(); let windowHeight: number = mainWindow.windowRect.height; let windowWidth: number = mainWindow.windowRect.width; - let windowWidthVp = windowWidth / display.getDefaultDisplaySync().densityPixels; - let windowHeightVp = windowHeight / display.getDefaultDisplaySync().densityPixels; + let windowWidthVp = windowWidth / (display.getDefaultDisplaySync().densityDPI / 160); + let windowHeightVp = windowHeight / (display.getDefaultDisplaySync().densityDPI / 160); let heightBp: string = ''; let aspectRatio: number = windowHeightVp / windowWidthVp; if (aspectRatio < 0.8) { diff --git a/features/home/src/main/ets/constants/HomeConstants.ets b/features/home/src/main/ets/constants/HomeConstants.ets index 85a3fda506a531e53cc8011a9e6ff27613a8f42e..72759c33ecc9a31e28cca617cffcaa371ae05522 100644 --- a/features/home/src/main/ets/constants/HomeConstants.ets +++ b/features/home/src/main/ets/constants/HomeConstants.ets @@ -161,10 +161,6 @@ export class HomeConstants { * New video rows template. */ static readonly NEW_VIDEO_ROWS_TEMPLATE: string = '1fr'; - /** - * Search top tab bar list space list. - */ - static readonly SEARCH_TAB_LIST_SPACES: string[] = ['16vp', '24vp', '36vp']; /** * Main daily video button text. */ @@ -249,7 +245,7 @@ export class HomeConstants { /** * Video grid description height. */ - static readonly VIDEO_GRID_DESCRIPTION_HEIGHT: number = 114; + static readonly VIDEO_GRID_DESCRIPTION_HEIGHT: number = 120; /** * New video aspect ratio. */ @@ -257,11 +253,11 @@ export class HomeConstants { /** * New video description height. */ - static readonly NEW_VIDEO_DESCRIPTION_HEIGHT: number = 45; + static readonly NEW_VIDEO_DESCRIPTION_HEIGHT: number = 71; /** * Daily video description height. */ - static readonly DAILY_VIDEO_DESCRIPTION_HEIGHT: number[] = [103, 62]; + static readonly DAILY_VIDEO_DESCRIPTION_HEIGHT: number[] = [103, 88, 115, 62]; /** * Previous two ratio list. */ @@ -269,7 +265,7 @@ export class HomeConstants { /** * Banner aspect ratio list. */ - static readonly BANNER_RATIOS: number[] = [1.5, 1.83, 2.33]; + static readonly BANNER_RATIOS: number[] = [1.49, 1.6, 2.1]; /** * Home header height for sm. */ @@ -339,4 +335,8 @@ export class HomeConstants { * Animation duration. */ static readonly ANIMATION_DURATION: number = 500; + /** + * Item width of IconView. + */ + static readonly ICONVIEW_ITEM_WIDTH: number[] = [40, 43, 45]; } \ No newline at end of file diff --git a/features/home/src/main/ets/view/BannerView.ets b/features/home/src/main/ets/view/BannerView.ets index e80f75464072c3f01eb5d7d633ee4458491b25ae..9981a4acfa1354ef9621e7a2ab3296946a3bdeea 100644 --- a/features/home/src/main/ets/view/BannerView.ets +++ b/features/home/src/main/ets/view/BannerView.ets @@ -53,23 +53,6 @@ export struct BannerView { this.bannerDataSource = new BannerDataSource(this.bannerImgList); } - @Styles - focusedStyles(): void { - .border({ - width: $r('app.float.focus_radius_width'), - color: $r('app.color.focus_radius_color'), - radius: $r('app.float.banner_focus_radius') - }) - } - - @Styles - normalStyles(): void { - .border({ - width: 0, - radius: $r('app.float.banner_focus_radius') - }) - } - build() { Column() { // Banner layout. @@ -77,24 +60,19 @@ export struct BannerView { Swiper() { LazyForEach(this.bannerDataSource, (item: Banner, index: number) => { Stack() { - Image(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? - item.getBannerImg().getImgSrcSm() : - item.getBannerImg().getImgSrc()) + Image(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? item.getBannerImg().getImgSrcSm() : + item.getBannerImg().getImgSrc()) .objectFit(ImageFit.Fill) .borderRadius($r('app.float.banner_img_border_radius')) .height(CommonConstants.FULL_PERCENT) .width(CommonConstants.FULL_PERCENT) .focusable(true) - .groupDefaultFocus(index === 0 ? true : false) - .stateStyles({ - normal: this.normalStyles, - focused: this.focusedStyles - }) + .zIndex(1) Column() { Text(item.getDescription().getIsLeftCenter().getValue(this.currentWidthBreakpoint) ? `${item.getDescription().getDescription()[0]}${item.getDescription().getDescription()[1]}` : - item.getDescription().getDescription()[0]) + item.getDescription().getDescription()[0]) .fontSize(item.getDescription().getFontSize().getValue(this.currentWidthBreakpoint)[0]) .fontWeight(item.getDescription().getFontWeight()[0]) .lineHeight(item.getDescription().getLineHeight().getValue(this.currentWidthBreakpoint)[0]) @@ -125,26 +103,35 @@ export struct BannerView { } .padding({ left: !item.getDescription().getIsLeftCenter().getValue(this.currentWidthBreakpoint) ? - item.getDescription().getLeftPosition().getValue(this.currentWidthBreakpoint)[0] : '0', + item.getDescription().getLeftPosition().getValue(this.currentWidthBreakpoint)[0] : '0', top: !item.getDescription().getIsTopCenter().getValue(this.currentWidthBreakpoint) ? - item.getDescription().getTopPosition().getValue(this.currentWidthBreakpoint)[0] : '0' + item.getDescription().getTopPosition().getValue(this.currentWidthBreakpoint)[0] : '0' }) .alignItems(item.getDescription().getIsLeftCenter().getValue(this.currentWidthBreakpoint) ? - HorizontalAlign.Center : HorizontalAlign.Start) + HorizontalAlign.Center : HorizontalAlign.Start) .justifyContent(!item.getDescription().getIsTopCenter().getValue(this.currentWidthBreakpoint) ? - FlexAlign.Start : FlexAlign.Center) + FlexAlign.Start : FlexAlign.Center) .height(CommonConstants.FULL_PERCENT) .width(CommonConstants.FULL_PERCENT) + .zIndex(2) } .height(item.getBannerImg().getHeight().getValue(this.currentWidthBreakpoint)) .width(CommonConstants.FULL_PERCENT) // The width and height vary with the container assembly and the aspect ratio remains unchanged. .aspectRatio(new BreakpointType(HomeConstants.BANNER_RATIOS[0], HomeConstants.BANNER_RATIOS[1], HomeConstants.BANNER_RATIOS[2]).getValue(this.currentWidthBreakpoint)) + .groupDefaultFocus(index === 0 ? true : false) + .focusable(true) + .padding({ + top: $r('app.float.banner_margin'), + bottom: $r('app.float.banner_margin'), + left: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? $r('app.float.banner_padding_sm') : 0, + right: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? $r('app.float.banner_padding_sm') : 0 + }) }, (item: Banner, index: number) => index + JSON.stringify(item)) } - .tabIndex(getTabIndex(HomeConstants.DIRECTION_LIST[2])) .index(2) + .tabIndex(getTabIndex(HomeConstants.DIRECTION_LIST[2])) .displayCount(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? 1 : HomeConstants.TWO) // Interval between banner images .itemSpace(HomeConstants.SWIPER_ITEM_SPACE) @@ -155,13 +142,13 @@ export struct BannerView { .selectedItemWidth($r('app.float.swiper_selected_item_width')) .selectedItemHeight($r('app.float.swiper_item_size')) .color($r('app.color.swiper_indicator')) + .bottom($r('app.float.indicator_bottom')) .selectedColor(Color.White) : false ) .loop(true) .width(CommonConstants.FULL_PERCENT) .visibility((this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG) && - (this.currentTopIndex === 1) ? - Visibility.None : Visibility.Visible) + (this.currentTopIndex === 1) ? Visibility.None : Visibility.Visible) .effectMode(EdgeEffect.None) // The sizes of the front and rear banners on the MD and LG devices are different. .prevMargin(new BreakpointType($r('app.float.swiper_prev_next_margin_sm'), @@ -207,24 +194,13 @@ export struct BannerView { .height(this.getBannerNewHeight(this.windowWidth)) .width(CommonConstants.FULL_PERCENT) .visibility((this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG) && - (this.currentTopIndex === 1) ? - Visibility.Visible : Visibility.None) + (this.currentTopIndex === 1) ? Visibility.Visible : Visibility.None) .padding({ left: $r('app.float.banner_padding_sm'), right: $r('app.float.banner_padding_sm') }) } .width(CommonConstants.FULL_PERCENT) - .margin({ - top: $r('app.float.banner_margin'), - bottom: $r('app.float.banner_margin') - }) - .padding({ - left: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? $r('app.float.banner_padding_sm') : - '0', - right: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? $r('app.float.banner_padding_sm') : - '0' - }) .visibility(this.currentTopIndex === 2 ? Visibility.None : Visibility.Visible) Row() { @@ -329,7 +305,7 @@ struct BannerText { build() { Stack() { Image(((this.index === 0) || (this.index === 1)) ? this.banner.getBannerImg().getImgSrcSm() : - this.banner.getBannerImg().getImgSrc()) + this.banner.getBannerImg().getImgSrc()) .width(CommonConstants.FULL_PERCENT) .height(CommonConstants.FULL_PERCENT) .objectFit(ImageFit.Fill) @@ -338,14 +314,13 @@ struct BannerText { Column() { Text(this.banner.getDescription().getIsLeftCenter().getValue(this.currentWidthBreakpoint) ? `${this.banner.getDescription().getDescription()[0]}${this.banner.getDescription().getDescription()[1]}` : - this.banner.getDescription().getDescription()[0]) + this.banner.getDescription().getDescription()[0]) .fontSize(this.banner.getDescription().getFontSize().getValue(this.currentWidthBreakpoint)[0]) .fontWeight(this.banner.getDescription().getFontWeight()[0]) .lineHeight(this.banner.getDescription().getLineHeight().getValue(this.currentWidthBreakpoint)[0]) .fontColor(Color.White) .letterSpacing(HomeConstants.BANNER_TEXT_LETTER_SPACES[2]) .maxLines(1) - Text(this.banner.getDescription().getDescription()[1]) .fontSize(this.banner.getDescription().getFontSize().getValue(this.currentWidthBreakpoint)[0]) .fontWeight(this.banner.getDescription().getFontWeight()[0]) @@ -354,29 +329,27 @@ struct BannerText { .letterSpacing(HomeConstants.BANNER_TEXT_LETTER_SPACES[2]) .maxLines(1) .visibility(this.banner.getDescription().getIsLeftCenter().getValue(this.currentWidthBreakpoint) ? - Visibility.None : Visibility.Visible) + Visibility.None : Visibility.Visible) Text(this.banner.getDescription().getDescription()[2]) .fontSize(this.banner.getDescription().getFontSize().getValue(this.currentWidthBreakpoint)[1]) .fontWeight(this.banner.getDescription().getFontWeight()[1]) .lineHeight(this.banner.getDescription().getLineHeight().getValue(this.currentWidthBreakpoint)[1]) .fontColor(Color.White) - .margin({ - top: this.banner.getDescription().getTopPosition().getValue(this.currentWidthBreakpoint)[1] - }) + .margin({ top: this.banner.getDescription().getTopPosition().getValue(this.currentWidthBreakpoint)[1] }) .letterSpacing(HomeConstants.BANNER_TEXT_LETTER_SPACES[1]) .maxLines(1) } .padding({ left: !this.banner.getDescription().getIsLeftCenter().getValue(this.currentWidthBreakpoint) ? - this.banner.getDescription().getLeftPosition().getValue(this.currentWidthBreakpoint)[0] : '0', + this.banner.getDescription().getLeftPosition().getValue(this.currentWidthBreakpoint)[0] : '0', top: !this.banner.getDescription().getIsTopCenter().getValue(this.currentWidthBreakpoint) ? - this.banner.getDescription().getTopPosition().getValue(this.currentWidthBreakpoint)[0] : '0' + this.banner.getDescription().getTopPosition().getValue(this.currentWidthBreakpoint)[0] : '0' }) .alignItems(this.banner.getDescription().getIsLeftCenter().getValue(this.currentWidthBreakpoint) ? - HorizontalAlign.Center : HorizontalAlign.Start) + HorizontalAlign.Center : HorizontalAlign.Start) .justifyContent(!this.banner.getDescription().getIsTopCenter().getValue(this.currentWidthBreakpoint) ? - FlexAlign.Start : FlexAlign.Center) + FlexAlign.Start : FlexAlign.Center) .width(CommonConstants.FULL_PERCENT) .height(CommonConstants.FULL_PERCENT) } diff --git a/features/home/src/main/ets/view/CommonView.ets b/features/home/src/main/ets/view/CommonView.ets index 4b840f3c1ff0a9b91aa130c3bd3e1f6812310921..1f922e8bdc1b3b1e5d54368db7946d66449a7fa6 100644 --- a/features/home/src/main/ets/view/CommonView.ets +++ b/features/home/src/main/ets/view/CommonView.ets @@ -13,7 +13,7 @@ * limitations under the License. */ -import { BreakpointConstants, CommonConstants } from '@ohos/commons'; +import { BreakpointConstants, BreakpointType, CommonConstants } from '@ohos/commons'; import { HomeConstants } from '../constants/HomeConstants'; @Component @@ -86,51 +86,34 @@ export struct SubtitleComponent { private title: ResourceStr = ''; build() { - Row() { - Text(this.title) - .fontSize($r('app.float.sub_title_font')) - .fontWeight(CommonConstants.FONT_WEIGHT_500) - .fontColor(this.currentTopIndex === 2 ? Color.White : $r('app.color.normal_font_color')) - } - .height($r('app.float.sub_title_row_height')) - .width(CommonConstants.FULL_PERCENT) - .margin({ - left: $r('app.float.sub_title_row_margin'), - right: $r('app.float.sub_title_row_margin') - }) + Text(this.title) + .fontSize($r('app.float.sub_title_font')) + .fontWeight(CommonConstants.FONT_WEIGHT_500) + .fontColor(this.currentTopIndex === 2 ? Color.White : $r('app.color.normal_font_color')) + .lineHeight($r('app.float.sub_title_row_height')) + .width(CommonConstants.FULL_PERCENT) + .padding({ + left: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint), + right: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint)}) } } @Component export struct VideoImgComponent { private imgSrc?: Resource; - - @Styles focusedStyles(): void { - .border({ - width: $r('app.float.focus_radius_width'), - color: $r('app.color.focus_radius_color'), - radius: $r('app.float.banner_focus_radius') - }) - } - - @Styles normalStyles(): void { - .border({ - width: 0, - radius: $r('app.float.banner_focus_radius') - }) - } + private index: number = 0; build() { Image(this.imgSrc ? this.imgSrc : '') .focusable(true) + .groupDefaultFocus(this.index === 0 ? true : false) .objectFit(ImageFit.Fill) .width(CommonConstants.FULL_PERCENT) .height(CommonConstants.FULL_PERCENT) .draggable(false) - .stateStyles({ - normal: this.normalStyles, - focused: this.focusedStyles - }) + .borderRadius($r('app.float.banner_focus_radius')) } } diff --git a/features/home/src/main/ets/view/DailyVideo.ets b/features/home/src/main/ets/view/DailyVideo.ets index 72d55123c12d19d20d74b49090f2270d4c66886d..781f5fa0777e9b9b552b88cf0de2fc0df2fa4bd5 100644 --- a/features/home/src/main/ets/view/DailyVideo.ets +++ b/features/home/src/main/ets/view/DailyVideo.ets @@ -18,7 +18,6 @@ import { BreakpointType } from '@ohos/commons'; import { HomeConstants } from '../constants/HomeConstants'; import { VideoImage, VideoImgViewModel } from '../viewmodel/VideoImgViewModel'; import { getTabIndex, SubtitleComponent, VideoImgComponent, VideoImgPlay, VideoImgRating } from './CommonView'; -import { display } from '@kit.ArkUI'; @Component export struct DailyVideo { @@ -29,27 +28,6 @@ export struct DailyVideo { private dailyVideoImgList: VideoImage[] = new VideoImgViewModel().getDailyVideoImgList(); private mainDailyVideoImg: VideoImage = new VideoImgViewModel().getMainDailyVideoImg(); - @Styles focusedMainStyles(): void { - .border({ - width: $r('app.float.focus_radius_width'), - color: $r('app.color.focus_radius_color'), - radius: { - topLeft: $r('app.float.daily_main_focus_radius'), - topRight: $r('app.float.daily_main_focus_radius') - } - }) - } - - @Styles normalMainStyles(): void { - .border({ - width: 0, - radius: { - topLeft: $r('app.float.daily_main_focus_radius'), - topRight: $r('app.float.daily_main_focus_radius') - } - }) - } - build() { Column() { SubtitleComponent({ title: HomeConstants.HOME_SUB_TITLES[1] }) @@ -60,11 +38,7 @@ export struct DailyVideo { md: BreakpointConstants.GRID_ROW_COLUMNS[0], lg: BreakpointConstants.GRID_ROW_COLUMNS[0] }, - gutter: $r('app.float.grid_row_gutter'), - breakpoints: { - value: ['320vp', '600vp', '840vp'], - reference: BreakpointsReference.WindowSize - } + gutter: $r('app.float.grid_row_gutter') }) { // Main video section. GridCol({ @@ -82,9 +56,9 @@ export struct DailyVideo { .width(CommonConstants.FULL_PERCENT) .height(CommonConstants.FULL_PERCENT) .draggable(false) - .stateStyles({ - normal: this.normalMainStyles, - focused: this.focusedMainStyles + .borderRadius({ + topLeft: $r('app.float.daily_main_focus_radius'), + topRight: $r('app.float.daily_main_focus_radius') }) VideoImgPlay() @@ -188,6 +162,15 @@ export struct DailyVideo { .borderRadius($r('app.float.card_radius')) .backgroundColor($r('app.color.home_component_background')) } + .padding({ + top: $r('app.float.sub_title_row_margin'), + bottom: this.currentWidthBreakpoint !== BreakpointConstants.BREAKPOINT_SM ? + $r('app.float.sub_title_row_margin') : 0, + left: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint), + right: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? + $r('app.float.home_content_padding_sm') : 0 + }) // Sub video section. GridCol({ @@ -242,6 +225,16 @@ export struct DailyVideo { .rowsTemplate(CommonConstants.VIDEO_GRID_COLUMNS[0]) .rowsGap($r('app.float.daily_grid_gap')) .columnsGap($r('app.float.daily_grid_gap')) + .padding({ + top: this.currentWidthBreakpoint !== BreakpointConstants.BREAKPOINT_SM ? + $r('app.float.sub_title_row_margin') : $r('app.float.focus_more_size'), + bottom: this.currentWidthBreakpoint !== BreakpointConstants.BREAKPOINT_SM ? + $r('app.float.sub_title_row_margin') : $r('app.float.focus_more_size'), + left: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? + $r('app.float.home_content_padding_sm') : $r('app.float.focus_more_size'), + right: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint) + }) } } } @@ -265,10 +258,18 @@ export struct DailyVideo { } // Calculate the height of a single image and title, and calculate the total height of the grid layout. result = (result - HomeConstants.VIDEO_GRID_ITEM_SPACE) / HomeConstants.VIDEO_DIALOG_ASPECT_RATIO; - if (currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM && !isMain) { - return (result + HomeConstants.DAILY_VIDEO_DESCRIPTION_HEIGHT[0] + HomeConstants.HEIGHT_UNIT); + if (currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM) { + if (isMain) { + return (result + HomeConstants.DAILY_VIDEO_DESCRIPTION_HEIGHT[0] + HomeConstants.HEIGHT_UNIT); + } else { + return (result + HomeConstants.DAILY_VIDEO_DESCRIPTION_HEIGHT[2] + HomeConstants.HEIGHT_UNIT); + } } else { - return (result + HomeConstants.DAILY_VIDEO_DESCRIPTION_HEIGHT[1] + HomeConstants.HEIGHT_UNIT); + if (!isMain) { + return (result + HomeConstants.DAILY_VIDEO_DESCRIPTION_HEIGHT[1] + HomeConstants.HEIGHT_UNIT); + } else { + return (result + HomeConstants.DAILY_VIDEO_DESCRIPTION_HEIGHT[3] + HomeConstants.HEIGHT_UNIT); + } } } } \ No newline at end of file diff --git a/features/home/src/main/ets/view/Home.ets b/features/home/src/main/ets/view/Home.ets index 430cf3c5777bd8d049f5ca2691c1d5d58d844512..fbbd5ec191530e86ece777e7e665b442af01f559 100644 --- a/features/home/src/main/ets/view/Home.ets +++ b/features/home/src/main/ets/view/Home.ets @@ -114,14 +114,17 @@ export struct Home { .tabBar(this.BottomTabBuilder(this.tabList[0], 0)) TabContent() { + Column() } .tabBar(this.BottomTabBuilder(this.tabList[1], 1)) TabContent() { + Column() } .tabBar(this.BottomTabBuilder(this.tabList[2], 2)) TabContent() { + Column() } .tabBar(this.BottomTabBuilder(this.tabList[3], 3)) } @@ -134,11 +137,12 @@ export struct Home { .barMode(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? BarMode.Scrollable : BarMode.Fixed, { nonScrollableLayoutStyle: LayoutStyle.ALWAYS_CENTER }) .vertical(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG) + .barOverlap(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG && this.currentTopIndex === 2 ? true : + false) + .barBackgroundBlurStyle(BlurStyle.NONE) .barBackgroundColor(this.currentTopIndex === 2 && this.currentBottomIndex === 0 ? (this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? $r('app.color.side_bar_background') : $r('app.color.home_content_background')) : $r('app.color.tab_background_color')) - .barOverlap(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG && this.currentTopIndex === 2 ? true : - false) .onChange((index: number) => { this.currentBottomIndex = index; }) diff --git a/features/home/src/main/ets/view/HomeContent.ets b/features/home/src/main/ets/view/HomeContent.ets index 83aa4737cf251b492a857c51995db68ae43d97f2..098ad1d7e2668eb5dfea99cec2226dd4017adcb2 100644 --- a/features/home/src/main/ets/view/HomeContent.ets +++ b/features/home/src/main/ets/view/HomeContent.ets @@ -43,18 +43,9 @@ export struct HomeContent { BannerView() IconView() RecommendedVideo() - Column() { - NewVideoRelease() - DailyVideo() - PreviousVideo() - } - .padding({ - left: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), - $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint), - right: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), - $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint) - }) - .width(CommonConstants.FULL_PERCENT) + NewVideoRelease() + DailyVideo() + PreviousVideo() } // Set the background image to cover the side and top tabs. .backgroundImage(this.currentTopIndex === 2 && !this.isSearching ? new BreakpointType( diff --git a/features/home/src/main/ets/view/HomeHeader.ets b/features/home/src/main/ets/view/HomeHeader.ets index a749b1fb00ba0e5b3c85ccab8c00b08365fa1f4e..7634098d8bcfb4ee49cfb12f40fd2a096c4bfd5e 100644 --- a/features/home/src/main/ets/view/HomeHeader.ets +++ b/features/home/src/main/ets/view/HomeHeader.ets @@ -27,36 +27,6 @@ export struct HomeHeader { @StorageLink('currentWidthBreakpoint') currentWidthBreakpoint: string = BreakpointConstants.BREAKPOINT_LG; @StorageLink('currentTopIndex') currentTopIndex: number = 0; - @Styles topFocusedStyles(): void { - .border({ - width: $r('app.float.focus_radius_width'), - color: $r('app.color.focus_radius_color'), - radius: $r('app.float.text_focus_radius') - }) - } - - @Styles topNormalStyles(): void { - .border({ - width: 0, - radius: $r('app.float.text_focus_radius') - }) - } - - @Styles inputFocusedStyles(): void { - .border({ - width: $r('app.float.focus_radius_width'), - color: $r('app.color.focus_radius_color'), - radius: $r('app.float.input_focus_radius') - }) - } - - @Styles inputNormalStyles(): void { - .border({ - width: 0, - radius: $r('app.float.input_focus_radius') - }) - } - build() { Column() { GridRow({ @@ -99,10 +69,6 @@ export struct HomeHeader { HomeConstants.BACKGROUND_CHANGE_HEIGHT[1], HomeConstants.BACKGROUND_CHANGE_HEIGHT[2]) .getValue(this.currentWidthBreakpoint) && this.currentTopIndex === 2 ? $r('app.color.home_content_background') : Color.Transparent) - .padding({ - left: $r('app.float.search_top_padding'), - right: $r('app.float.search_top_padding') - }) } .width(CommonConstants.FULL_PERCENT) } @@ -111,47 +77,45 @@ export struct HomeHeader { TopTabBar() { Row() { Column() { - List({ - space: new BreakpointType(HomeConstants.SEARCH_TAB_LIST_SPACES[0], HomeConstants.SEARCH_TAB_LIST_SPACES[1], - HomeConstants.SEARCH_TAB_LIST_SPACES[2]).getValue(this.currentWidthBreakpoint) - }) { + List() { ForEach(HomeConstants.TOP_TOPIC_LIST, (item: string, index: number) => { ListItem() { - Column() { - Text(item) - .fontSize(this.currentTopIndex === index ? $r('app.float.search_tab_font_selected') : - $r('app.float.search_tab_font')) - .fontWeight(this.currentTopIndex === index ? CommonConstants.FONT_WEIGHT_700 : - CommonConstants.FONT_WEIGHT_500) - .width(this.currentTopIndex === index ? $r('app.float.top_text_width_selected') : - $r('app.float.top_text_width')) - .textAlign(TextAlign.Center) - .fontColor(this.currentTopIndex === 2 ? Color.White : $r('app.color.normal_font_color')) - .focusable(true) - .groupDefaultFocus(index === 0 ? true : false) - } - .stateStyles({ - normal: this.topNormalStyles, - focused: this.topFocusedStyles - }) - .height(index === this.currentTopIndex ? $r('app.float.top_tab_list_height_selected') : - $r('app.float.top_tab_list_height')) + Text(item) + .fontSize(this.currentTopIndex === index ? $r('app.float.search_tab_font_selected') : + $r('app.float.search_tab_font')) + .fontWeight(this.currentTopIndex === index ? CommonConstants.FONT_WEIGHT_700 : + CommonConstants.FONT_WEIGHT_500) + .width(this.currentTopIndex === index ? $r('app.float.top_text_width_selected') : + $r('app.float.top_text_width')) + .textAlign(TextAlign.Center) + .fontColor(this.currentTopIndex === 2 ? Color.White : $r('app.color.normal_font_color')) + .lineHeight(index === this.currentTopIndex ? $r('app.float.top_tab_list_height_selected') : + $r('app.float.top_tab_list_height')) + .focusable(true) + .groupDefaultFocus(index === 0 ? true : false) + .borderRadius($r('app.float.text_focus_radius')) } + .align(Alignment.Center) .margin({ top: this.currentTopIndex === index ? $r('app.float.top_tab_list_top_selected') : $r('app.float.top_tab_list_top'), bottom: this.currentTopIndex === index ? $r('app.float.top_tab_list_bottom_selected') : $r('app.float.top_tab_list_bottom') }) + .padding({ + left: new BreakpointType(8, 12, 18).getValue(this.currentWidthBreakpoint), + right: new BreakpointType(8, 12, 18).getValue(this.currentWidthBreakpoint) + }) .onClick(() => { this.currentTopIndex = index; this.scrollHeight = 0; }) - }, (item: string, index: number) => index + JSON.stringify(item)) + }, (item: number, index: number) => index + JSON.stringify(item)) } .tabIndex(getTabIndex(HomeConstants.DIRECTION_LIST[1])) .scrollBar(BarState.Off) .listDirection(Axis.Horizontal) + .padding({ left: $r('app.float.search_top_padding') }) } .alignItems(HorizontalAlign.Center) .layoutWeight(1) @@ -159,7 +123,10 @@ export struct HomeHeader { Image($r('app.media.ic_public_more')) .width($r('app.float.top_tab_img_size')) .height($r('app.float.top_tab_img_size')) - .margin({ left: $r('app.float.top_tab_img_margin') }) + .margin({ + left: $r('app.float.top_tab_img_margin'), + right: $r('app.float.top_tab_img_margin') + }) .fillColor(this.currentTopIndex === 2 ? Color.White : Color.Black) .visibility(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? Visibility.Visible : Visibility.None) } @@ -192,13 +159,10 @@ export struct HomeHeader { this.isSearching = true; } }) - .stateStyles({ - normal: this.inputNormalStyles, - focused: this.inputFocusedStyles - }) .enterKeyType(EnterKeyType.Go) .enableKeyboardOnFocus(false) .backgroundColor(this.currentTopIndex === 2 ? $r('app.color.search_bar_background') : '') + .tabIndex(getTabIndex(HomeConstants.DIRECTION_LIST[1])) // Search image. Image(this.currentTopIndex === 2 && this.currentWidthBreakpoint ? $r("app.media.ic_public_search_white") : @@ -207,7 +171,7 @@ export struct HomeHeader { .height($r('app.float.search_img_size')) .margin({ left: $r('app.float.search_img_left') }) } - .tabIndex(getTabIndex(HomeConstants.DIRECTION_LIST[1])) + // .tabIndex(getTabIndex(HomeConstants.DIRECTION_LIST[1])) .alignSelf(ItemAlign.Center) .layoutWeight(1) @@ -223,8 +187,10 @@ export struct HomeHeader { .margin({ left: $r('app.float.history_img_left') }) .visibility(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? Visibility.None : Visibility.Visible) } - .padding({ left: this.currentWidthBreakpoint !== BreakpointConstants.BREAKPOINT_SM ? - $r('app.float.search_bar_row_padding') : '0' }) + .padding({ + left: $r('app.float.search_top_padding'), + right: $r('app.float.search_top_padding') + }) .justifyContent(FlexAlign.Center) .width(CommonConstants.FULL_PERCENT) .height(CommonConstants.FULL_PERCENT) diff --git a/features/home/src/main/ets/view/IconView.ets b/features/home/src/main/ets/view/IconView.ets index 007415e07f5d67652c4484501e8ca16167ec3219..5460c3625781a934421537af5c33999c4468a8ae 100644 --- a/features/home/src/main/ets/view/IconView.ets +++ b/features/home/src/main/ets/view/IconView.ets @@ -26,81 +26,70 @@ export struct IconView { @StorageLink('currentTopIndex') currentTopIndex: number = 0; private iconList: VideoIcon[] = new IconViewModel().getIconList(); - @Styles focusedStyles(): void { - .border({ - width: $r('app.float.focus_radius_width'), - color: $r('app.color.focus_radius_color'), - radius: $r('app.float.icon_focus_radius') - }) - } - - @Styles normalStyles(): void { - .border({ - width: 0, - radius: $r('app.float.icon_focus_radius') - }) - } - build() { // Icon swiper. Column() { - Swiper() { + List({ space: this.getSpace(this.windowWidth, this.currentWidthBreakpoint) }) { ForEach(this.iconList, (item: VideoIcon, index: number) => { - Column() { - Image(item.getImage()) - .width($r('app.float.icon_img_size')) - .height($r('app.float.icon_img_size')) - .margin({ bottom: $r('app.float.icon_img_bottom_margin') }) - .focusable(true) - .groupDefaultFocus(index === 0 ? true : false) - .stateStyles({ - normal: this.normalStyles, - focused: this.focusedStyles - }) + ListItem() { + Column() { + Image(item.getImage()) + .width($r('app.float.icon_img_size')) + .height($r('app.float.icon_img_size')) + .margin({ bottom: $r('app.float.icon_img_bottom_margin') }) + .focusable(true) + .groupDefaultFocus(index === 0 ? true : false) + .borderRadius($r('app.float.icon_img_radius')) - Text(item.getName()) - .fontSize($r('app.float.icon_list_font_size')) - .fontWeight(FontWeight.Normal) - .lineHeight($r('app.float.icon_list_font_height')) - .fontColor(this.currentTopIndex === 2 ? Color.White : Color.Black) + Text(item.getName()) + .fontSize($r('app.float.icon_list_font_size')) + .fontWeight(FontWeight.Normal) + .lineHeight($r('app.float.icon_list_font_height')) + .fontColor(this.currentTopIndex === 2 ? Color.White : Color.Black) + } + .alignItems(HorizontalAlign.Center) + .justifyContent(FlexAlign.Center) + .height($r('app.float.icon_list_height')) } - .alignItems(HorizontalAlign.Center) - .height($r('app.float.icon_list_height')) + .padding({ + right: index === this.iconList.length - 1 ? this.getSpace(this.windowWidth, this.currentWidthBreakpoint) / 2 : 0 + }) }, (item: VideoIcon) => JSON.stringify(item)) } + .clip(false) + .listDirection(Axis.Horizontal) + .scrollBar(BarState.Off) + .scrollSnapAlign(ScrollSnapAlign.START) + .edgeEffect(EdgeEffect.None) + .chainAnimation(true) .tabIndex(getTabIndex(HomeConstants.DIRECTION_LIST[3])) - // The number of different breakpoints is different. - .displayCount(new BreakpointType(CommonConstants.FOUR, HomeConstants.SIX, HomeConstants.EIGHT) - .getValue(this.currentWidthBreakpoint)) - .nextMargin(this.getNextMargin(this.windowWidth, this.currentWidthBreakpoint)) - .indicator(false) .width(CommonConstants.FULL_PERCENT) - .loop(false) - .effectMode(EdgeEffect.None) - .displayMode(SwiperDisplayMode.AUTO_LINEAR) } .padding({ - left: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? $r('app.float.icon_list_column_padding_lg') : - $r('app.float.icon_list_column_padding') + left: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint) + }) + .margin({ + top: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.icon_list_column_margin_lg') : 0 }) - .margin({ top: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.icon_list_column_margin_lg') : $r('app.float.icon_list_column_margin') }) .visibility(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG && this.currentTopIndex === 2 ? Visibility.None : Visibility.Visible) } - getNextMargin(windowWidth: number, currentWidthBreakpoint: string): string { + getSpace(windowWidth: number, currentWidthBreakpoint: string): number { // Obtain the window width and subtract the blank parts on both sides. - let result: number = px2vp(windowWidth) - new BreakpointType(HomeConstants.VIDEO_GRID_MARGIN[0], + let result: number = px2vp(windowWidth) - (new BreakpointType(HomeConstants.VIDEO_GRID_MARGIN[0], HomeConstants.VIDEO_GRID_MARGIN[1], HomeConstants.VIDEO_GRID_MARGIN[2]).getValue(this.currentWidthBreakpoint) / - HomeConstants.TWO; + HomeConstants.TWO) - getContext(this).resourceManager.getNumber($r('app.float.icon_img_size').id) / 2; if (currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM) { - result = result / HomeConstants.DISPLAYED_ICON_NUMBER[0]; + result = (result - HomeConstants.ICONVIEW_ITEM_WIDTH[0] * CommonConstants.FOUR) / CommonConstants.FOUR; } else if (currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_MD) { - result = result / HomeConstants.DISPLAYED_ICON_NUMBER[1]; + result = (result - HomeConstants.ICONVIEW_ITEM_WIDTH[1] * HomeConstants.SIX) / HomeConstants.SIX; } else { - result = (result - HomeConstants.LG_SIDEBAR_WIDTH) / HomeConstants.DISPLAYED_ICON_NUMBER[2]; + result = (result - HomeConstants.LG_SIDEBAR_WIDTH - HomeConstants.ICONVIEW_ITEM_WIDTH[2] * HomeConstants.EIGHT) / + HomeConstants.EIGHT; } - return result + HomeConstants.HEIGHT_UNIT; + return result; } } \ No newline at end of file diff --git a/features/home/src/main/ets/view/NewVideoRelease.ets b/features/home/src/main/ets/view/NewVideoRelease.ets index 4194d60da4906d4fec06b797b085c8b6d9002054..031e2279a789e5bab2493ea9e2bcb8aa7ff8e20f 100644 --- a/features/home/src/main/ets/view/NewVideoRelease.ets +++ b/features/home/src/main/ets/view/NewVideoRelease.ets @@ -29,15 +29,16 @@ export struct NewVideoRelease { build() { Column() { - SubtitleComponent({ title:HomeConstants.HOME_SUB_TITLES[0] }) + SubtitleComponent({ title: HomeConstants.HOME_SUB_TITLES[0] }) + .margin({ top: $r('app.float.sub_title_row_margin') }) // Video grid. Grid() { - ForEach(this.newVideoImgList, (item: VideoImage) => { + ForEach(this.newVideoImgList, (item: VideoImage, index: number) => { GridItem() { Column() { Stack({ alignContent: Alignment.Bottom }) { - VideoImgComponent({ imgSrc:item.getImgSrc() }) + VideoImgComponent({ imgSrc:item.getImgSrc(), index: index }) VideoImgPlay() VideoImgRating({ rating: item.getRating() }) } @@ -54,6 +55,14 @@ export struct NewVideoRelease { }, (item: VideoImage, index: number) => index + JSON.stringify(item)) } .tabIndex(getTabIndex(HomeConstants.DIRECTION_LIST[5])) + .padding({ + left: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint), + right: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint), + top: $r('app.float.sub_title_row_margin'), + bottom: $r('app.float.sub_title_row_margin') + }) .columnsTemplate(new BreakpointType(CommonConstants.VIDEO_GRID_COLUMNS[1], CommonConstants.VIDEO_GRID_COLUMNS[3], CommonConstants.VIDEO_GRID_COLUMNS[4]).getValue(this.currentWidthBreakpoint)) .rowsTemplate(HomeConstants.NEW_VIDEO_ROWS_TEMPLATE) diff --git a/features/home/src/main/ets/view/PreviousVideo.ets b/features/home/src/main/ets/view/PreviousVideo.ets index e7ad7c7de4849ecda49ca2936d12228cd7f29dc4..d87ce9a8e09c13d3eb5074ecc58f314de3d0b2c5 100644 --- a/features/home/src/main/ets/view/PreviousVideo.ets +++ b/features/home/src/main/ets/view/PreviousVideo.ets @@ -28,201 +28,213 @@ export struct PreviousVideo { @Consume('pageInfo') pageInfo: VideoNavPathStack; private previousVideoImgListOne: VideoImage[] = new VideoImgViewModel().getPreviousVideoOne(); - @Styles focusedStyles(): void { - .border({ - width: $r('app.float.focus_radius_width'), - color: $r('app.color.focus_radius_color'), - radius: { - topLeft: $r('app.float.previous_two_radius'), - topRight: $r('app.float.previous_two_radius') - } - }) - } - - @Styles normalStyles(): void { - .border({ - width: 0, - radius: { - topLeft: $r('app.float.previous_two_radius'), - topRight: $r('app.float.previous_two_radius') - } - }) - } - build() { Column() { SubtitleComponent({ title: HomeConstants.HOME_SUB_TITLES[2] }) + .margin({ bottom: $r('app.float.sub_title_row_margin') }) - GridRow({ - columns: { - sm: BreakpointConstants.GRID_ROW_COLUMNS[2], - md: BreakpointConstants.GRID_ROW_COLUMNS[0], - lg: BreakpointConstants.GRID_ROW_COLUMNS[1] - }, - gutter: $r('app.float.grid_row_gutter') - }) { - ForEach(this.previousVideoImgListOne, (item: VideoImage, index: number) => { - GridCol({ - span: { - sm: BreakpointConstants.GRID_COLUMN_SPANS[5], - md: BreakpointConstants.GRID_COLUMN_SPANS[1], - lg: BreakpointConstants.GRID_COLUMN_SPANS[3] - } - }) { - Row() { - Image(item.getImgSrc()) - .objectFit(ImageFit.Fill) - .margin({ right: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? - $r('app.float.previous_one_image_margin_sm') : $r('app.float.previous_one_image_margin') }) - .layoutWeight(CommonConstants.THREE) - .height(CommonConstants.FULL_PERCENT) - .borderRadius($r('app.float.banner_img_border_radius')) - - Column() { - Text(item.getTitle()) - .fontSize(new BreakpointType($r('app.float.previous_one_title_font_sm'), - $r('app.float.previous_one_title_font_md'), $r('app.float.previous_one_title_font_lg')) - .getValue(this.currentWidthBreakpoint)) - .fontWeight(CommonConstants.FONT_WEIGHT_500) - .maxLines(2) - .textOverflow({ overflow: TextOverflow.Ellipsis }) - Text(item.getContent()) - .fontSize(new BreakpointType($r('app.float.previous_one_content_font_sm'), - $r('app.float.previous_one_content_font_md'), $r('app.float.previous_one_content_font_lg')) - .getValue(this.currentWidthBreakpoint)) - .opacity(CommonConstants.TEXT_OPACITY[1]) - .fontWeight(FontWeight.Normal) - .margin({ top: $r('app.float.previous_one_content_margin') }) - .maxLines(1) - Text(item.getOtherInfo()) - .fontSize(new BreakpointType($r('app.float.previous_one_content_font_sm'), - $r('app.float.previous_one_content_font_md'), $r('app.float.previous_one_content_font_lg')) - .getValue(this.currentWidthBreakpoint)) - .opacity(CommonConstants.TEXT_OPACITY[1]) - .fontWeight(FontWeight.Normal) - .margin({ top: $r('app.float.previous_one_content_margin') }) - .maxLines(1) + Row() { + GridRow({ + columns: { + sm: BreakpointConstants.GRID_ROW_COLUMNS[2], + md: BreakpointConstants.GRID_ROW_COLUMNS[0], + lg: BreakpointConstants.GRID_ROW_COLUMNS[1] + }, + gutter: $r('app.float.grid_row_gutter') + }) { + ForEach(this.previousVideoImgListOne, (item: VideoImage, index: number) => { + GridCol({ + span: { + sm: BreakpointConstants.GRID_COLUMN_SPANS[5], + md: BreakpointConstants.GRID_COLUMN_SPANS[1], + lg: BreakpointConstants.GRID_COLUMN_SPANS[3] + } + }) { + Row() { + Image(item.getImgSrc()) + .objectFit(ImageFit.Fill) + .margin({ right: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? + $r('app.float.previous_one_image_margin_sm') : $r('app.float.previous_one_image_margin') }) + .layoutWeight(CommonConstants.THREE) + .height(CommonConstants.FULL_PERCENT) + .borderRadius($r('app.float.banner_img_border_radius')) + .focusable(true) - Row() { - Button(index === 0 ? HomeConstants.HOME_BUTTON_TEXT[1] : HomeConstants.HOME_BUTTON_TEXT[2]) - .borderRadius($r('app.float.previous_one_button_radius')) - .backgroundColor($r('app.color.previous_one_button_origin')) + Column() { + Text(item.getTitle()) + .fontSize(new BreakpointType($r('app.float.previous_one_title_font_sm'), + $r('app.float.previous_one_title_font_md'), $r('app.float.previous_one_title_font_lg')) + .getValue(this.currentWidthBreakpoint)) .fontWeight(CommonConstants.FONT_WEIGHT_500) - .fontSize(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_one_button_font_lg') : $r('app.float.previous_one_button_font')) - .fontColor(Color.White) - .height(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_one_button_height_lg') : $r('app.float.previous_one_button_height')) - .layoutWeight(1) - .groupDefaultFocus(index === 0 ? true : false) - .onClick(() => { - this.pageInfo.setPageName(CommonConstants.PAGE_NAMES[1]); - this.pageInfo.pushPath({ name: CommonConstants.PAGE_NAMES[1] }); - }) + .maxLines(2) + .textOverflow({ overflow: TextOverflow.Ellipsis }) + Text(item.getContent()) + .fontSize(new BreakpointType($r('app.float.previous_one_content_font_sm'), + $r('app.float.previous_one_content_font_md'), $r('app.float.previous_one_content_font_lg')) + .getValue(this.currentWidthBreakpoint)) + .opacity(CommonConstants.TEXT_OPACITY[1]) + .fontWeight(FontWeight.Normal) + .margin({ top: $r('app.float.previous_one_content_margin') }) + .maxLines(1) + Text(item.getOtherInfo()) + .fontSize(new BreakpointType($r('app.float.previous_one_content_font_sm'), + $r('app.float.previous_one_content_font_md'), $r('app.float.previous_one_content_font_lg')) + .getValue(this.currentWidthBreakpoint)) + .opacity(CommonConstants.TEXT_OPACITY[1]) + .fontWeight(FontWeight.Normal) + .margin({ top: $r('app.float.previous_one_content_margin') }) + .maxLines(1) - Blank() - .width(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_MD ? - $r('app.float.previous_blank_width_md') : $r('app.float.previous_blank_width')) + Row() { + Button(index === 0 ? HomeConstants.HOME_BUTTON_TEXT[1] : HomeConstants.HOME_BUTTON_TEXT[2]) + .borderRadius($r('app.float.previous_one_button_radius')) + .backgroundColor($r('app.color.previous_one_button_origin')) + .fontWeight(CommonConstants.FONT_WEIGHT_500) + .fontSize(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_one_button_font_lg') : $r('app.float.previous_one_button_font')) + .fontColor(Color.White) + .height(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_one_button_height_lg') : $r('app.float.previous_one_button_height')) + .layoutWeight(1) + .focusable(true) + .onClick(() => { + this.pageInfo.setPageName(CommonConstants.PAGE_NAMES[1]); + this.pageInfo.pushPath({ name: CommonConstants.PAGE_NAMES[1] }); + }) - Button(HomeConstants.HOME_BUTTON_TEXT[3]) - .borderRadius($r('app.float.previous_one_button_radius')) - .backgroundColor($r('app.color.button_background')) - .fontWeight(CommonConstants.FONT_WEIGHT_500) - .fontSize(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_one_button_font_lg') : $r('app.float.previous_one_button_font')) - .fontColor($r('app.color.previous_one_button_origin')) - .height(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_one_button_height_lg') : $r('app.float.previous_one_button_height')) - .layoutWeight(1) + Blank() + .width(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_MD ? + $r('app.float.previous_blank_width_md') : $r('app.float.previous_blank_width')) + + Button(HomeConstants.HOME_BUTTON_TEXT[3]) + .borderRadius($r('app.float.previous_one_button_radius')) + .backgroundColor($r('app.color.button_background')) + .fontWeight(CommonConstants.FONT_WEIGHT_500) + .fontSize(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_one_button_font_lg') : $r('app.float.previous_one_button_font')) + .fontColor($r('app.color.previous_one_button_origin')) + .height(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_one_button_height_lg') : $r('app.float.previous_one_button_height')) + .layoutWeight(1) + .focusable(true) + } + .width(CommonConstants.FULL_PERCENT) + .alignItems(VerticalAlign.Bottom) + .layoutWeight(1) } - .width(CommonConstants.FULL_PERCENT) - .alignItems(VerticalAlign.Bottom) - .layoutWeight(1) + .alignItems(HorizontalAlign.Start) + .justifyContent(FlexAlign.Start) + .layoutWeight(CommonConstants.FOUR) } - .alignItems(HorizontalAlign.Start) - .justifyContent(FlexAlign.Start) - .layoutWeight(CommonConstants.FOUR) + .aspectRatio(CommonConstants.PREVIOUS_ONE_ROW_RATIO) + .width(CommonConstants.FULL_PERCENT) + .padding({ + top: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? + $r('app.float.previous_one_row_padding_sm') : $r('app.float.previous_one_row_padding'), + bottom: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? + $r('app.float.previous_one_row_padding_sm') : $r('app.float.previous_one_row_padding'), + left: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? + $r('app.float.previous_one_row_padding_sm') : $r('app.float.previous_one_row_padding'), + right: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? + $r('app.float.previous_one_row_padding_sm') : $r('app.float.previous_one_row_padding') + }) + .backgroundColor($r('app.color.home_component_background')) + .borderRadius($r('app.float.card_radius')) } - .aspectRatio(CommonConstants.PREVIOUS_ONE_ROW_RATIO) - .width(CommonConstants.FULL_PERCENT) - .padding({ - top: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? - $r('app.float.previous_one_row_padding_sm') : $r('app.float.previous_one_row_padding'), - bottom: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? - $r('app.float.previous_one_row_padding_sm') : $r('app.float.previous_one_row_padding'), - left: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? - $r('app.float.previous_one_row_padding_sm') : $r('app.float.previous_one_row_padding'), - right: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM ? - $r('app.float.previous_one_row_padding_sm') : $r('app.float.previous_one_row_padding') - }) - .backgroundColor($r('app.color.home_component_background')) - .borderRadius($r('app.float.card_radius')) - } - }, (item: VideoImage, index: number) => index + JSON.stringify(item)) + .focusable(true) + }, (item: VideoImage, index: number) => index + JSON.stringify(item)) + } + .focusable(true) + .padding({ + left: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint), + right: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint) + }) + } + .width(CommonConstants.FULL_PERCENT) - ForEach(this.previousVideoImgListTwo, (item: VideoImage, index: number) => { - GridCol({ - span: { - sm: BreakpointConstants.GRID_COLUMN_SPANS[6], - md: BreakpointConstants.GRID_COLUMN_SPANS[4], - lg: BreakpointConstants.GRID_COLUMN_SPANS[4] - } - }) { - Column() { - Image(item.getImgSrc()) + Row() { + GridRow({ + columns: { + sm: BreakpointConstants.GRID_ROW_COLUMNS[2], + md: BreakpointConstants.GRID_ROW_COLUMNS[0], + lg: BreakpointConstants.GRID_ROW_COLUMNS[1] + }, + gutter: $r('app.float.grid_row_gutter') + }) { + ForEach(this.previousVideoImgListTwo, (item: VideoImage, index: number) => { + GridCol({ + span: { + sm: BreakpointConstants.GRID_COLUMN_SPANS[6], + md: BreakpointConstants.GRID_COLUMN_SPANS[4], + lg: BreakpointConstants.GRID_COLUMN_SPANS[4] + } + }) { + Column() { + Image(item.getImgSrc()) + .width(CommonConstants.FULL_PERCENT) + .aspectRatio(PreviousVideoUtil.getImgAspectRatio(this.currentWidthBreakpoint, index)) + .objectFit(ImageFit.Fill) + .focusable(true) + .borderRadius({ + topLeft: $r('app.float.previous_two_radius'), + topRight: $r('app.float.previous_two_radius') + }) + + Column() { + Text(item.getTitle()) + .fontWeight(FontWeight.Normal) + .fontSize(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_two_title_font_lg') : $r('app.float.previous_two_title_font')) + .maxLines(1) + .lineHeight(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_two_title_line_lg') : $r('app.float.previous_two_title_line')) + Text(item.getContent()) + .fontWeight(FontWeight.Normal) + .fontSize(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_two_content_font_lg') : $r('app.float.previous_two_content_font')) + .margin({ top: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_two_content_margin_lg') : $r('app.float.previous_two_content_margin') }) + .opacity(CommonConstants.TEXT_OPACITY[0]) + .maxLines(1) + .lineHeight(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_two_content_line_lg') : $r('app.float.previous_two_content_line')) + } + .alignItems(HorizontalAlign.Start) + .height(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_two_column_height_lg') : $r('app.float.previous_two_column_height')) .width(CommonConstants.FULL_PERCENT) - .aspectRatio(PreviousVideoUtil.getImgAspectRatio(this.currentWidthBreakpoint, index)) - .objectFit(ImageFit.Fill) - .focusable(true) - .stateStyles({ - normal: this.normalStyles, - focused: this.focusedStyles + .padding({ + top: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_two_column_padding_lg') : $r('app.float.previous_two_column_padding'), + bottom: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_two_column_bottom_lg') : $r('app.float.previous_two_column_bottom'), + left: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_two_column_padding_lg') : $r('app.float.previous_two_column_padding'), + right: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? + $r('app.float.previous_two_column_padding_lg') : $r('app.float.previous_two_column_padding') }) - - Column() { - Text(item.getTitle()) - .fontWeight(FontWeight.Normal) - .fontSize(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_two_title_font_lg') : $r('app.float.previous_two_title_font')) - .maxLines(1) - .lineHeight(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_two_title_line_lg') : $r('app.float.previous_two_title_line')) - Text(item.getContent()) - .fontWeight(FontWeight.Normal) - .fontSize(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_two_content_font_lg') : $r('app.float.previous_two_content_font')) - .margin({ top: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_two_content_margin_lg') : $r('app.float.previous_two_content_margin') }) - .opacity(CommonConstants.TEXT_OPACITY[0]) - .maxLines(1) - .lineHeight(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_two_content_line_lg') : $r('app.float.previous_two_content_line')) } - .alignItems(HorizontalAlign.Start) - .height(this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_two_column_height_lg') : $r('app.float.previous_two_column_height')) - .width(CommonConstants.FULL_PERCENT) - .padding({ - top: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_two_column_padding_lg') : $r('app.float.previous_two_column_padding'), - bottom: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_two_column_bottom_lg') : $r('app.float.previous_two_column_bottom'), - left: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_two_column_padding_lg') : $r('app.float.previous_two_column_padding'), - right: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? - $r('app.float.previous_two_column_padding_lg') : $r('app.float.previous_two_column_padding') - }) + .translate({ y: (((index === 2) || (index === 3)) && (this.currentWidthBreakpoint === + BreakpointConstants.BREAKPOINT_MD)) ? HomeConstants.PREVIOUS_TWO_TRANSLATE_MD : '0' }) + .backgroundColor($r('app.color.home_component_background')) + .borderRadius($r('app.float.previous_two_radius')) } - .translate({ y: (((index === 2) || (index === 3)) && (this.currentWidthBreakpoint === - BreakpointConstants.BREAKPOINT_MD)) ? HomeConstants.PREVIOUS_TWO_TRANSLATE_MD : '0' }) - .backgroundColor($r('app.color.home_component_background')) - .borderRadius($r('app.float.previous_two_radius')) - } - }, (item: VideoImage, index: number) => index + JSON.stringify(item)) + }, (item: VideoImage, index: number) => index + JSON.stringify(item)) + } + .focusable(true) + .onBreakpointChange((breakPoints) => { + this.previousVideoImgListTwo = new VideoImgViewModel().getPreviousVideoTwo(breakPoints); + }) + .padding({ + left: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint), + right: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint) + }) } - .onBreakpointChange((breakPoints) => { - this.previousVideoImgListTwo = new VideoImgViewModel().getPreviousVideoTwo(breakPoints); - }) + .width(CommonConstants.FULL_PERCENT) } .tabIndex(getTabIndex(HomeConstants.DIRECTION_LIST[8])) .padding({ left: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG && this.currentTopIndex === 2 ? diff --git a/features/home/src/main/ets/view/RecommendedVideo.ets b/features/home/src/main/ets/view/RecommendedVideo.ets index 4a21ce383a3510683938c814241ca3bb89b027ba..2aa9fdb5d0a60bc7791a1a6a4e56b65e2c2f3a1d 100644 --- a/features/home/src/main/ets/view/RecommendedVideo.ets +++ b/features/home/src/main/ets/view/RecommendedVideo.ets @@ -30,152 +30,125 @@ export struct RecommendedVideo { @StorageLink('currentTopIndex') currentTopIndex: number = 0; @State isShowingRecommendBorder: boolean = false; @State currentRecommendFocusIndex: number = 0; - @State recommendedCurrentVideo: number = -1; @State videoImgList: VideoImage[] = new VideoImgViewModel().getVideoImgList(); private videoDialogController?: CustomDialogController; private windowUtil?: WindowUtil; - @Styles focusedStyles(): void { - .border({ - width: $r('app.float.focus_radius_width'), - color: $r('app.color.focus_radius_color'), - radius: $r('app.float.banner_focus_radius') - }) - } - - @Styles normalStyles(): void { - .border({ - width: 0, - radius: $r('app.float.banner_focus_radius') - }) - } - build() { - Column() { - // Video grid layout. - Grid() { - ForEach(this.videoImgList, (item: VideoImage, index: number) => { - GridItem() { - Column() { - Stack({ alignContent: Alignment.Center }) { - Image(item.getImgSrc()) - .focusable(true) - .groupDefaultFocus(index === 0 ? true : false) - .objectFit(ImageFit.Fill) - .width(this.recommendedCurrentVideo === index ? HomeConstants.PERCENT_HUNDRED_AND_FIVE : - CommonConstants.FULL_PERCENT) - .height(this.recommendedCurrentVideo === index ? HomeConstants.PERCENT_HUNDRED_AND_FIVE : - CommonConstants.FULL_PERCENT) - .draggable(false) - .stateStyles({ - normal: this.normalStyles, - focused: this.focusedStyles - }) - .id(JSON.stringify(item)) - Column() { - VideoImgRating({ rating: item.getRating() }) - } + // Video grid layout. + Grid() { + ForEach(this.videoImgList, (item: VideoImage, index: number) => { + GridItem() { + Column() { + Stack({ alignContent: Alignment.Center }) { + Image(item.getImgSrc()) + .focusable(true) + .groupDefaultFocus(index === 0 ? true : false) + .objectFit(ImageFit.Fill) .width(CommonConstants.FULL_PERCENT) .height(CommonConstants.FULL_PERCENT) - .alignItems(HorizontalAlign.End) - .justifyContent(FlexAlign.End) + .draggable(false) + .borderRadius($r('app.float.banner_focus_radius')) + .id(JSON.stringify(item)) + Column() { + VideoImgRating({ rating: item.getRating() }) } .width(CommonConstants.FULL_PERCENT) - // The width and height vary with the container assembly and the aspect ratio remains unchanged. - .aspectRatio(HomeConstants.VIDEO_DIALOG_ASPECT_RATIO) - .onHover((isHover: boolean) => { - if (isHover) { - this.recommendedCurrentVideo = index; - } else { - this.recommendedCurrentVideo = -1; - } - }) - .gesture( - LongPressGesture({ repeat: false }) - .onAction(() => { - if (index !== 0) { - Logger.info(`Please long press the first image`); - return; - } - // Obtains all attributes of a component. - let modePosition: componentUtils.ComponentInfo = - componentUtils.getRectangleById(JSON.stringify(item)); - let windowOffset = modePosition.windowOffset; - let size = modePosition.size; - // Obtains the height of the component from the top. - let rectTop: number = px2vp(windowOffset.y); - let rectTop2: number = px2vp(windowOffset.y + Math.floor(size.height)); - // Obtains the width of the component from the left. - let rectLeft: number = px2vp(windowOffset.x); - let topHeightNeeded: number = new BreakpointType(HomeConstants.VIDEO_DIALOG_HEIGHTS[0], + .height(CommonConstants.FULL_PERCENT) + .alignItems(HorizontalAlign.End) + .justifyContent(FlexAlign.End) + } + .focusable(true) + .width(CommonConstants.FULL_PERCENT) + // The width and height vary with the container assembly and the aspect ratio remains unchanged. + .aspectRatio(HomeConstants.VIDEO_DIALOG_ASPECT_RATIO) + .hoverEffect(HoverEffect.Scale) + .gesture( + LongPressGesture({ repeat: false }) + .onAction(() => { + if (index !== 0) { + Logger.info(`Please long press the first image`); + return; + } + // Obtains all attributes of a component. + let modePosition: componentUtils.ComponentInfo = + componentUtils.getRectangleById(JSON.stringify(item)); + let windowOffset = modePosition.windowOffset; + let size = modePosition.size; + // Obtains the height of the component from the top. + let rectTop: number = px2vp(windowOffset.y); + let rectTop2: number = px2vp(windowOffset.y + Math.floor(size.height)); + // Obtains the width of the component from the left. + let rectLeft: number = px2vp(windowOffset.x); + let topHeightNeeded: number = new BreakpointType(HomeConstants.VIDEO_DIALOG_HEIGHTS[0], + HomeConstants.VIDEO_DIALOG_HEIGHTS[1], HomeConstants.VIDEO_DIALOG_HEIGHTS[2]) + .getValue(this.currentWidthBreakpoint) + rectTop - rectTop2; + if (this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM) { + topHeightNeeded += HomeConstants.HOME_HEADER_HEIGHT_SM; + } + let dialogYOffset: number; + // Adaptive pop-up window expansion direction. + if (topHeightNeeded < rectTop) { + dialogYOffset = rectTop2 - new BreakpointType(HomeConstants.VIDEO_DIALOG_HEIGHTS[0], HomeConstants.VIDEO_DIALOG_HEIGHTS[1], HomeConstants.VIDEO_DIALOG_HEIGHTS[2]) - .getValue(this.currentWidthBreakpoint) + rectTop - rectTop2; - if (this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_SM) { - topHeightNeeded += HomeConstants.HOME_HEADER_HEIGHT_SM; - } - let dialogYOffset: number; - // Adaptive pop-up window expansion direction. - if (topHeightNeeded < rectTop) { - dialogYOffset = rectTop2 - new BreakpointType(HomeConstants.VIDEO_DIALOG_HEIGHTS[0], - HomeConstants.VIDEO_DIALOG_HEIGHTS[1], HomeConstants.VIDEO_DIALOG_HEIGHTS[2]) - .getValue(this.currentWidthBreakpoint); - } else { - dialogYOffset = rectTop; + .getValue(this.currentWidthBreakpoint); + } else { + dialogYOffset = rectTop; + } + this.windowUtil = WindowUtil.getInstance(); + let isLayoutFullScreen: boolean = true; + let mainWindow = this.windowUtil!.getMainWindow(); + isLayoutFullScreen = mainWindow!.getWindowProperties().isLayoutFullScreen; + // Subtract the width and height of the window in the 2in1 device. + if (deviceInfo.deviceType === CommonConstants.DEVICE_TYPE && !isLayoutFullScreen) { + dialogYOffset -= HomeConstants.WINDOW_UNDEFINED_TOP; + rectLeft -= HomeConstants.WINDOW_UNDEFINED_LEFT; + } else { + Logger.info(`No need to subtract extra height`); + } + this.videoDialogController = new CustomDialogController({ + builder: VideoDialog(), + autoCancel: true, + customStyle: true, + alignment: DialogAlignment.TopStart, + offset: { + dx: rectLeft, + dy: dialogYOffset } - this.windowUtil = WindowUtil.getInstance(); - let isLayoutFullScreen: boolean = true; - let mainWindow = this.windowUtil!.getMainWindow(); - isLayoutFullScreen = mainWindow!.getWindowProperties().isLayoutFullScreen; - // Subtract the width and height of the window in the 2in1 device. - if (deviceInfo.deviceType === CommonConstants.DEVICE_TYPE && !isLayoutFullScreen) { - dialogYOffset -= HomeConstants.WINDOW_UNDEFINED_TOP; - rectLeft -= HomeConstants.WINDOW_UNDEFINED_LEFT; - } else { - Logger.info(`No need to subtract extra height`); - } - this.videoDialogController = new CustomDialogController({ - builder: VideoDialog(), - autoCancel: true, - customStyle: true, - alignment: DialogAlignment.TopStart, - offset: { - dx: rectLeft, - dy: dialogYOffset - } - }); - // Display the customized pop-up window to play the video. - this.videoDialogController.open(); - })) - .bindContextMenu(RightClickMenu(this.currentWidthBreakpoint), ResponseType.RightClick) + }); + // Display the customized pop-up window to play the video. + this.videoDialogController.open(); + })) + .bindContextMenu(RightClickMenu(this.currentWidthBreakpoint), ResponseType.RightClick) - VideoTitle({ title: item.getTitle() }) - VideoContent({ content: item.getContent() }) - } - .alignItems(HorizontalAlign.Start) + VideoTitle({ title: item.getTitle() }) + VideoContent({ content: item.getContent() }) } - }, (item: VideoImage, index: number) => index + JSON.stringify(item)) - } - .tabIndex(getTabIndex(HomeConstants.DIRECTION_LIST[4])) - .editMode(false) - // Sets the number of grid layout columns and evenly divides the width. - .columnsTemplate(this.videoGridColumn) - .rowsTemplate(CommonConstants.VIDEO_GRID_COLUMNS[0]) - .width(CommonConstants.FULL_PERCENT) - .rowsGap($r('app.float.video_grid_gap')) - .columnsGap($r('app.float.video_grid_gap')) - // Dynamically calculates the total height based on the following numbers of breakpoints. - .height(this.getGridHeight(this.videoGridColumn, this.currentWidthBreakpoint, this.windowWidth)) - .padding({ - left: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG && this.currentTopIndex === 2 ? - new BreakpointType($r('app.float.home_recommended_padding_sm'), $r('app.float.home_recommended_padding_md'), - $r('app.float.home_recommended_padding_lg')).getValue(this.currentWidthBreakpoint) : - new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), - $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint), - right: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), - $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint), - top: $r('app.float.recommended_video_padding_top') - }) + .alignItems(HorizontalAlign.Start) + } + }, (item: VideoImage, index: number) => index + JSON.stringify(item)) } + .tabIndex(getTabIndex(HomeConstants.DIRECTION_LIST[4])) + .editMode(false) + // Sets the number of grid layout columns and evenly divides the width. + .columnsTemplate(this.videoGridColumn) + .rowsTemplate(CommonConstants.VIDEO_GRID_COLUMNS[0]) + .width(CommonConstants.FULL_PERCENT) + .rowsGap($r('app.float.video_grid_gap')) + .columnsGap($r('app.float.video_grid_gap')) + // Dynamically calculates the total height based on the following numbers of breakpoints. + .height(this.getGridHeight(this.videoGridColumn, this.currentWidthBreakpoint, this.windowWidth)) + .padding({ + left: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG && this.currentTopIndex === 2 ? + new BreakpointType($r('app.float.home_recommended_padding_sm'), $r('app.float.home_recommended_padding_md'), + $r('app.float.home_recommended_padding_lg')).getValue(this.currentWidthBreakpoint) : + new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint), + right: new BreakpointType($r('app.float.home_content_padding_sm'), $r('app.float.home_content_padding_md'), + $r('app.float.home_content_padding_lg')).getValue(this.currentWidthBreakpoint), + top: $r('app.float.recommended_video_padding_top'), + bottom: $r('app.float.recommended_video_padding_bottom') + }) // Zooming and pinching functions of the grid. .gesture(PinchGesture({ fingers: 2 }).onActionUpdate((event: GestureEvent) => { if (event.scale > 1 && this.currentWidthBreakpoint !== BreakpointConstants.BREAKPOINT_SM) { diff --git a/features/home/src/main/resources/base/element/color.json b/features/home/src/main/resources/base/element/color.json index 26d6c5920a4c75a0a86782ae66f03c1d82b5717a..1eb948ae93981eca88ae45a2eea7f8e5f8a7d76d 100644 --- a/features/home/src/main/resources/base/element/color.json +++ b/features/home/src/main/resources/base/element/color.json @@ -51,10 +51,6 @@ { "name": "tab_background_color", "value": "#F1F3F5" - }, - { - "name": "focus_radius_color", - "value": "#317AF7" } ] } \ No newline at end of file diff --git a/features/home/src/main/resources/base/element/float.json b/features/home/src/main/resources/base/element/float.json index 30e7b95b35dc1e7ffbdc271f7ca34f9316686ad5..f7cfb5c8a0746960b629f48a92ac83e84e8558b8 100644 --- a/features/home/src/main/resources/base/element/float.json +++ b/features/home/src/main/resources/base/element/float.json @@ -26,11 +26,11 @@ }, { "name": "banner_height_md", - "value": "170vp" + "value": "194vp" }, { "name": "banner_height_lg", - "value": "218vp" + "value": "242vp" }, { "name": "banner_text_1_font_sm", @@ -132,6 +132,10 @@ "name": "swiper_selected_item_width", "value": "12vp" }, + { + "name": "indicator_bottom", + "value": "12vp" + }, { "name": "new_banner_3_margin", "value": "6vp" @@ -148,6 +152,10 @@ "name": "icon_img_size", "value": "40vp" }, + { + "name": "icon_img_radius", + "value": "20vp" + }, { "name": "icon_img_bottom_margin", "value": "4vp" @@ -174,11 +182,7 @@ }, { "name": "icon_list_column_margin_lg", - "value": "16vp" - }, - { - "name": "icon_list_column_margin", - "value": "12vp" + "value": "4vp" }, { "name": "video_grid_gap", @@ -238,11 +242,11 @@ }, { "name": "search_tab_font_selected", - "value": "16fp" + "value": "24fp" }, { "name": "search_tab_font", - "value": "14fp" + "value": "18fp" }, { "name": "main_daily_rating_font_lg", @@ -542,11 +546,15 @@ }, { "name": "sub_title_row_height", - "value": "48vp" + "value": "22vp" }, { "name": "sub_title_row_margin", - "value": "24vp" + "value": "13vp" + }, + { + "name": "focus_more_size", + "value": "6vp" }, { "name": "video_img_size_lg", @@ -684,10 +692,6 @@ "name": "history_img_left", "value": "24vp" }, - { - "name": "search_bar_row_padding", - "value": "24vp" - }, { "name": "bottom_tab_bar_width_lg", "value": "96vp" @@ -800,6 +804,10 @@ "name": "recommended_video_padding_top", "value": "12vp" }, + { + "name": "recommended_video_padding_bottom", + "value": "6vp" + }, { "name": "immersive_text_1_font_sm", "value": "18fp" @@ -880,25 +888,17 @@ "name": "daily_small_img_radius", "value": "8vp" }, - { - "name": "focus_radius_width", - "value": "2vp" - }, { "name": "text_focus_radius", - "value": "8vp" - }, - { - "name": "input_focus_radius", - "value": "20vp" + "value": "4vp" }, { "name": "top_text_width_selected", - "value": "80vp" + "value": "48vp" }, { "name": "top_text_width", - "value": "60vp" + "value": "36vp" }, { "name": "banner_focus_radius", @@ -907,10 +907,6 @@ { "name": "daily_main_focus_radius", "value": "18vp" - }, - { - "name": "icon_focus_radius", - "value": "24vp" } ] } \ No newline at end of file diff --git a/features/videoDetail/src/main/ets/view/RelatedList.ets b/features/videoDetail/src/main/ets/view/RelatedList.ets index db96143bc6491d88f11156bf3458dc0d5fa77fb1..2988ad0f95745a84140c88221c8f7dea770ca8b0 100644 --- a/features/videoDetail/src/main/ets/view/RelatedList.ets +++ b/features/videoDetail/src/main/ets/view/RelatedList.ets @@ -199,7 +199,7 @@ export struct RelatedList { left: $r('app.float.sub_title_row_padding'), right: $r('app.float.sub_title_row_padding') }) - .height($r('app.float.sub_title_row_height')) + .height($r('app.float.sub_title_row_height_detail')) .width(CommonConstants.FULL_PERCENT) this.SubTitle(DetailConstants.SUB_TITLES[4]) @@ -281,7 +281,7 @@ export struct RelatedList { left: $r('app.float.sub_title_row_padding'), right: $r('app.float.sub_title_row_padding') }) - .height($r('app.float.sub_title_row_height')) + .height($r('app.float.sub_title_row_height_detail')) .width(CommonConstants.FULL_PERCENT) } @@ -308,7 +308,7 @@ export struct RelatedList { left: $r('app.float.sub_title_row_padding'), right: $r('app.float.sub_title_row_padding') }) - .height($r('app.float.sub_title_row_height')) + .height($r('app.float.sub_title_row_height_detail')) .width(CommonConstants.FULL_PERCENT) .alignItems(VerticalAlign.Center) } diff --git a/features/videoDetail/src/main/ets/view/SelfComment.ets b/features/videoDetail/src/main/ets/view/SelfComment.ets index 68823b17ba97d6498a3078f115b897a007ef971e..e5486af0c627210099d01cea19835716d38fabb4 100644 --- a/features/videoDetail/src/main/ets/view/SelfComment.ets +++ b/features/videoDetail/src/main/ets/view/SelfComment.ets @@ -67,6 +67,7 @@ export struct SelfComment { right: $r('app.float.self_comment_input_right') }) .width(CommonConstants.FULL_PERCENT) + .focusable(false) } .alignSelf(ItemAlign.Center) .layoutWeight(1) diff --git a/features/videoDetail/src/main/ets/view/VideoDetail.ets b/features/videoDetail/src/main/ets/view/VideoDetail.ets index dfe47e4da3896d0b5245798b5f8835b658895805..3ad89e54805737eb59601d8d8a298c82746dc6db 100644 --- a/features/videoDetail/src/main/ets/view/VideoDetail.ets +++ b/features/videoDetail/src/main/ets/view/VideoDetail.ets @@ -13,6 +13,7 @@ * limitations under the License. */ +import { KeyCode } from '@kit.InputKit'; import { deviceInfo } from '@kit.BasicServicesKit'; import { display, window } from '@kit.ArkUI'; import { AvPlayerUtil, DeviceScreen, Logger, WindowUtil, BreakpointConstants, CommonConstants, DisplayUtil, @@ -220,5 +221,22 @@ export struct VideoDetail { this.isHalfFolded = false; } }) + .onKeyEvent((event?: KeyEvent) => { + if (!event || event.type !== KeyType.Down) { + return; + } + if (event.keyCode === KeyCode.KEYCODE_SPACE) { + this.avPlayerUtil!.playerStateControl(); + } + if (event.keyCode === KeyCode.KEYCODE_ESCAPE) { + this.windowUtil!.recover(); + } + if (event.keyCode === KeyCode.KEYCODE_DPAD_RIGHT) { + this.avPlayerUtil!.fastForward(); + } + if (event.keyCode === KeyCode.KEYCODE_DPAD_LEFT) { + this.avPlayerUtil!.rewind(); + } + }) } } \ No newline at end of file diff --git a/features/videoDetail/src/main/ets/view/VideoPlayer.ets b/features/videoDetail/src/main/ets/view/VideoPlayer.ets index d606aa38751c57cdefada28131413449b46ba680..0948b00311664dec59357b7936698fd9a625ebec 100644 --- a/features/videoDetail/src/main/ets/view/VideoPlayer.ets +++ b/features/videoDetail/src/main/ets/view/VideoPlayer.ets @@ -93,6 +93,15 @@ export struct VideoPlayer { this.avPlayerUtil?.playerStateControl(); } }) + .priorityGesture( + TapGesture({ count: 2 }) + .onAction((event: GestureEvent) => { + if (event && deviceInfo.deviceType === CommonConstants.DEVICE_TYPE) { + this.isFullScreen = true; + this.windowUtil!.maximize(); + } + }) + ) Column() { Row() { @@ -169,6 +178,15 @@ export struct VideoPlayer { .width(CommonConstants.FULL_PERCENT) .justifyContent(FlexAlign.End) .visibility(this.isFullScreen && !this.isShowingSideBar ? Visibility.Visible : Visibility.None) + .priorityGesture( + TapGesture({ count: 2 }) + .onAction((event: GestureEvent) => { + if (event && deviceInfo.deviceType === CommonConstants.DEVICE_TYPE) { + this.windowUtil!.maximize(); + this.windowUtil!.recover(); + } + }) + ) Row() { TimeText({ time: this.currentTime }) @@ -202,9 +220,17 @@ export struct VideoPlayer { .fillColor(Color.White) .onClick(() => { this.isFullScreen = true; - if (deviceInfo.deviceType !== CommonConstants.DEVICE_TYPE) { - this.windowUtil!.disableWindowSystemBar(); - } + }) + + Image($r('app.media.ic_public_fullscreen')) + .height($r('app.float.enlarge_size')) + .width($r('app.float.enlarge_size')) + .margin({ right: $r('app.float.enlarge_margin') }) + .fillColor(Color.White) + .visibility(deviceInfo.deviceType === CommonConstants.DEVICE_TYPE ? Visibility.Visible : Visibility.None) + .onClick(() => { + this.isFullScreen = true; + this.windowUtil!.maximize(); }) } .width(CommonConstants.FULL_PERCENT) @@ -216,7 +242,8 @@ export struct VideoPlayer { .height($r('app.float.back_size')) .width($r('app.float.back_size')) .position({ - x: $r('app.float.back_position_x'), + x: this.currentWidthBreakpoint === BreakpointConstants.BREAKPOINT_LG ? $r('app.float.back_position_x') : + $r('app.float.back_position_x_lg'), y: $r('app.float.back_position_y') }) .fillColor(Color.White) @@ -236,6 +263,7 @@ export struct VideoPlayer { .layoutWeight(this.isFullScreen ? 1 : 0) .width(CommonConstants.FULL_PERCENT) .backgroundColor(Color.Black) + .focusable(false) } } diff --git a/features/videoDetail/src/main/resources/base/element/float.json b/features/videoDetail/src/main/resources/base/element/float.json index 70ccc262ea9edc7d10d76cf7cb7572b04c184bb8..9f11426850dd10679c67b0f8767fdc929d30e625 100644 --- a/features/videoDetail/src/main/resources/base/element/float.json +++ b/features/videoDetail/src/main/resources/base/element/float.json @@ -125,7 +125,7 @@ "value": "24vp" }, { - "name": "sub_title_row_height", + "name": "sub_title_row_height_detail", "value": "48vp" }, { @@ -376,6 +376,10 @@ "name": "back_position_x", "value": "24vp" }, + { + "name": "back_position_x_lg", + "value": "32vp" + }, { "name": "back_position_y", "value": "36vp" diff --git a/features/videoDetail/src/main/resources/base/media/ic_public_fullscreen.svg b/features/videoDetail/src/main/resources/base/media/ic_public_fullscreen.svg new file mode 100644 index 0000000000000000000000000000000000000000..f9af64b3ec38ffe6b11d9bc34be63f1abf448c79 --- /dev/null +++ b/features/videoDetail/src/main/resources/base/media/ic_public_fullscreen.svg @@ -0,0 +1,16 @@ + + + Created with Pixso. + + + + + + + + + + + + + diff --git a/screenshots/device/foldable_EN.jpg b/screenshots/device/foldable_EN.jpg new file mode 100644 index 0000000000000000000000000000000000000000..787eddd04ca34d6b345ac6b1de6a787e28c1e69e Binary files /dev/null and b/screenshots/device/foldable_EN.jpg differ diff --git a/screenshots/device/phone_EN.png b/screenshots/device/phone_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..93323e368a7582e926b3e27027a952a67df65cf6 Binary files /dev/null and b/screenshots/device/phone_EN.png differ diff --git a/screenshots/device/tablet_EN.png b/screenshots/device/tablet_EN.png new file mode 100644 index 0000000000000000000000000000000000000000..9f51cb80d4afcfc11c622552d128e7659dac87d8 Binary files /dev/null and b/screenshots/device/tablet_EN.png differ