News and Information Application Adapted to All Devices in HarmonyOS Next

SameX - Feb 28 - - Dev Community

News and Information Application Adapted to All Devices in HarmonyOS Next

This article aims to deeply explore the technical details of the Huawei HarmonyOS Next system and summarize them based on practical development practices. It mainly serves as a medium for technical sharing and communication. There may inevitably be some errors or omissions. Colleagues are welcome to put forward valuable opinions and questions so that we can make progress together. This article is original content, and any form of reprint must indicate the source and the original author.

In the ecosystem of HarmonyOS Next, creating a news and information application that is adapted to all devices and providing users with a consistent and high-quality reading experience is the pursuit of many developers. Next, we will deeply analyze the key technologies and design ideas involved in achieving this goal.

Architectural Design for Multi-device Adaptation

Common UI Structures of News Applications

Common UI structures of news applications include list style, card style, and grid style. The list-style structure is simple and clear, suitable for displaying a large number of news headlines, allowing users to quickly browse the news topics. The card-style structure presents each news item in the form of a card, including information such as images, titles, and abstracts, with a rich visual effect that can attract users' attention. The grid-style structure is often used to display multiple news items with small images, which can make full use of the screen space and is suitable for displaying rich information content on large-screen devices.

How HarmonyOS Next Addresses the Differential Layouts of Mobile Phones, Tablets, and PCs

  1. Mobile Phones: Mobile phone screens are relatively small, and simplicity and convenient operation are emphasized. A single-column layout is mainly adopted, and the news content is displayed in a card-style UI structure, making it convenient for users to slide and browse with one hand. Use an adaptive layout to enable the height and width of the cards to be automatically adjusted according to the mobile phone screen size, ensuring that the text and images are completely displayed.
  2. Tablets: Tablets have larger screens, and a dual-column or multi-column layout can be adopted to balance the amount of information displayed and the convenience of operation. Combine with a responsive layout to switch the layout structure under different breakpoints. For example, when the screen is relatively narrow, adopt a single-column card-style layout similar to that of a mobile phone, and when the screen becomes wider, switch to a dual-column card layout to improve the efficiency of information display.
  3. PCs: PC screens are even larger, and a more complex layout can be adopted. Usually, a three-column mode is used, with the navigation bar on the left, the information list in the middle, and the article details on the right. Use the grid layout system to precisely control the width and proportion of each column to achieve an efficient information display and operation process.

Using an Adaptive Layout to Achieve UI Changes within a Single Screen

In the news and information application, the adaptive layout is used to automatically adjust the UI elements within a single screen. For example, on the news detail page, the layout of images and text can be automatically adjusted according to the screen width. By setting the flexGrow and flexShrink properties of the Flex layout, when the screen becomes wider, the image and text areas can be stretched proportionally; when the screen becomes narrower, the text and images will automatically adjust in size to avoid blank or crowded situations.

@Entry
@Component
struct NewsDetailPage {
    @State articleImage: Resource = $r('app.media.newsImage')
    @State articleContent: string = 'This is the detailed content of a news article...'
    build() {
        Flex({ direction: FlexDirection.Row }) {
            Image(this.articleImage).width(200).height(150).objectFit(ImageFit.Contain).flexGrow(0).flexShrink(1)
            Column() {
                Text('News Title').fontSize(20).fontWeight(500)
                Text(this.articleContent).fontSize(14).opacity(0.8)
            }
              .flexGrow(1).flexShrink(1).paddingStart(10)
        }
          .width('100%').height('100%')
    }
}
Enter fullscreen mode Exit fullscreen mode

Implementing a Cross-device News Reading Interface

To implement a cross-device news reading interface, it is necessary to combine adaptive and responsive layouts. On different devices, adjust the display mode of news content according to the screen size and layout structure. On mobile phones, the news list is vertically arranged in the form of cards; on tablets and PCs, adjust to a dual-column or multi-column card layout according to the screen width. At the same time, ensure that the news detail page can provide a good reading experience on different devices, with clear text layout and normal image display.

Listening to Breakpoints to Implement the Three-column Mode (Navigation Bar + Information List + Article Details) on Large-screen Devices

On large-screen devices (such as PCs and some tablets), the three-column mode is implemented by listening to breakpoints. Use the GridRow and GridCol components in combination with breakpoint configurations to achieve the switching of different layouts.

@Entry
@Component
struct BigScreenNewsLayout {
    @State currentBreakpoint: string ='sm'
    @State articleList: Array<{ title: string, content: string }> = [
        { title: 'News 1', content: 'The content of News 1' },
        { title: 'News 2', content: 'The content of News 2' }
    ]
    @State selectedArticleIndex: number = 0
    build() {
        GridRow({ breakpoints: { value: ['840vp'], reference: BreakpointsReference.WindowSize } }) {
            GridCol({ span: { sm: 12, md: 3, lg: 2 } }) {
                // Navigation Bar
                Column() {
                    ForEach(articleList, (article, index) => {
                        Text(article.title).fontSize(16).onClick(() => {
                            this.selectedArticleIndex = index
                        })
                    })
                }
            }
            GridCol({ span: { sm: 12, md: 6, lg: 4 } }) {
                // Information List
                List() {
                    ForEach(articleList, (article, index) => {
                        ListItem() {
                            Text(article.title).fontSize(16)
                        }
                    })
                }
            }
            GridCol({ span: { sm: 12, md: 12, lg: 6 } }) {
                // Article Details
                Column() {
                    Text(articleList[this.selectedArticleIndex].content).fontSize(14)
                }
            }
        }
          .onBreakpointChange((breakpoint: string) => {
                this.currentBreakpoint = breakpoint
            })
    }
}
Enter fullscreen mode Exit fullscreen mode

By listening to the changes in breakpoints, when the screen width is greater than 840vp, switch to the three-column mode to improve the efficiency of information display and operation on large-screen devices.

Combining Swiper + Grid to Adjust the Arrangement of Information Cards on Mobile Phones

On mobile phones, in order to improve the efficiency of users browsing news, the combination of Swiper + Grid is adopted to adjust the arrangement of information cards. Swiper is used to achieve the carousel effect of the cards to display popular news; Grid is used to reasonably arrange other news cards within the limited screen space.

@Entry
@Component
struct MobileNewsLayout {
    @State newsData: Array<{ title: string, image: Resource }> = [
        { title: 'News 1', image: $r('app.media.news1Image') },
        { title: 'News 2', image: $r('app.media.news2Image') },
        { title: 'News 3', image: $r('app.media.news3Image') }
    ]
    build() {
        Column() {
            Swiper() {
                ForEach(newsData.slice(0, 3), (news) => {
                    GridRow() {
                        GridCol({ span: 12 }) {
                            Column() {
                                Image(news.image).width('100%').height(150).objectFit(ImageFit.Contain)
                                Text(news.title).fontSize(16).textAlign(TextAlign.Center)
                            }
                        }
                    }
                })
            }
            .autoPlay(true).indicator(true)
            GridRow() {
                ForEach(newsData.slice(3), (news) => {
                    GridCol({ span: 6 }) {
                        Column() {
                            Image(news.image).width('100%').height(100).objectFit(ImageFit.Contain)
                            Text(news.title).fontSize(14).textAlign(TextAlign.Center)
                        }
                    }
                })
            }
        }
          .width('100%').height('100%')
    }
}
Enter fullscreen mode Exit fullscreen mode

In this way, not only can popular news be highlighted, but also more news content can be displayed within the limited screen space.

Adaptation in Free Window Mode to Ensure that the Content Does Not Shift when the Window is Adjusted

In the free window mode, to ensure that the content does not shift, the application needs to be optimized by combining adaptive and responsive layouts. By setting window size limit parameters, such as minWindowWidth, maxWindowHeight, etc., avoid layout confusion caused by excessive changes in the window size. At the same time, use the capabilities of line wrapping and hiding in the adaptive layout, as well as the breakpoint adjustment of the responsive layout, to ensure that the content can be automatically re-typeset when the window size changes.

@Entry
@Component
struct FreeWindowAdaptiveLayout {
    @State currentBreakpoint: string ='sm'
    build() {
        GridRow({ breakpoints: { value: ['600vp'], reference: BreakpointsReference.WindowSize } }) {
            GridCol({ span: { sm: 12, md: 6 } }) {
                Column() {
                    // News Content
                    Text('This is a news content that needs to be displayed normally under different window sizes').fontSize(14)
                }
            }
            GridCol({ span: { sm: 12, md: 6 } }) {
                // Related Image
                Image($r('app.media.newsImage')).width('100%').aspectRatio(1).when(this.currentBreakpoint ==='sm', (image) => image.height(100)).when(this.currentBreakpoint!=='sm', (image) => image.height(150))
            }
        }
          .onBreakpointChange((breakpoint: string) => {
                this.currentBreakpoint = breakpoint
            })
    }
}
Enter fullscreen mode Exit fullscreen mode

When the window size changes, adjust the layout in a timely manner by listening to the breakpoints to ensure the normal display of the content.

Optimizing the Experience and Dynamic Adaptation Strategies

Optimization with Media Queries: Dynamically Adjusting Fonts, Images, Spacing, etc. under Different Screen Sizes

Use media queries to dynamically adjust the font size, image size, and spacing according to different screen sizes. On small-screen devices, appropriately reduce the font and image sizes and increase the spacing between elements to facilitate user operation; on large-screen devices, increase the font and image sizes and reduce the spacing to improve the density of information display.

@Entry
@Component
struct MediaQueryOptimization {
    @State currentBreakpoint: string ='sm'
    build() {
        Column() {
            Text('News Title').fontSize(this.currentBreakpoint ==='sm'? 16 : 20).fontWeight(500)
            Image($r('app.media.newsImage')).width(this.currentBreakpoint ==='sm'? 100 : 200).height(this.currentBreakpoint ==='sm'? 100 : 150).objectFit(ImageFit.Contain)
            Text('News Content').fontSize(this.currentBreakpoint ==='sm'? 12 : 14).opacity(0.8).padding({ top: this.currentBreakpoint ==='sm'? 5 : 10 })
        }
          .width('100%').height('100%')
          .onBreakpointChange((breakpoint: string) => {
                this.currentBreakpoint = breakpoint
            })
    }
}
Enter fullscreen mode Exit fullscreen mode

Presentation Modes of the Navigation Bar on Different Devices (Hiding, Folding, Sidebar Switching)

On mobile phones, to save screen space, the navigation bar can be hidden or folded, and users can evoke the navigation by clicking a specific button. On tablets and PCs, a sidebar form can be adopted to always display the navigation options for the convenience of user operation.

@Entry
@Component
struct NavBarAdaptation {
    @State isNavBarVisible: boolean = false
    @State currentBreakpoint: string ='sm'
    build() {
        Column() {
            if (this.currentBreakpoint ==='sm') {
                Button('Expand Navigation').onClick(() => {
                    this.isNavBarVisible =!this.isNavBarVisible
                })
                if (this.isNavBarVisible) {
                    Column() {
                        // Navigation Options
                        Text('Home').fontSize(16).onClick(() => { /* Navigation Logic */ })
                        Text('Categories').fontSize(16).onClick(() => { /* Navigation Logic */ })
                    }
                }
            } else {
                // Sidebar Navigation on Tablets and PCs
                SideBarContainer(SideBarContainerType.Embed) {
                    Column() {
                        Text('Home').fontSize(16).onClick(() => { /* Navigation Logic */ })
                        Text('Categories').fontSize(16).onClick(() => { /* Navigation Logic */ })
                    }
                }
                  .sideBarWidth(200).showSideBar(true)
            }
        }
          .width('100%').height('100%')
          .onBreakpointChange((breakpoint: string) => {
                this.currentBreakpoint = breakpoint
                if (breakpoint!=='sm') {
                    this.isNavBarVisible = true
                }
            })
    }
}
Enter fullscreen mode Exit fullscreen mode

User Interaction Optimization (Keyboard/Mouse Operations on Large-screen Devices vs. Touch Gestures on Mobile Devices)

On large-screen devices, make full use of the operation advantages of the keyboard and mouse, such as using keyboard shortcuts for navigation and operation, and displaying more information when the mouse hovers. On mobile devices, optimize touch gesture operations, such as sliding to browse the news list and clicking to expand the details. By detecting the device input method, provide the most suitable interaction method for different devices to enhance the user experience.

@Entry
@Component
struct InteractionOptimization {
    @State deviceType: string = 'unknown'
    @State isHover: boolean = false
    aboutToAppear() {
        // Get the device type
        this.deviceType = deviceInfo.deviceType
    }
    build() {
        Column() {
            if (this.deviceType === 'tablet' || this.deviceType === 'pc') {
                // Large-screen Devices
                Text('News Title').fontSize(20).onHover((isHover) => {
                    this.isHover = isHover
                }).when(this.isHover, (text) => text.color('#0A59F7'))
            } else {
                // Mobile Devices
                Text('News Title').fontSize(16).onClick(() => { /* News Detail Logic */ })
            }
        }
          .width('100%').height('100%')
    }
}
Enter fullscreen mode Exit fullscreen mode

Through the above architectural design for multi-device adaptation, layout optimization, and comprehensive application of various technologies, we can create a news and information application that is adapted to all devices in HarmonyOS Next, providing users with a high-quality and consistent reading experience.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .