DEV Community

SameX
SameX

Posted on

Responsive Layout in HarmonyOS Next —— Cross-device Adaptive Solution

Responsive Layout in HarmonyOS Next —— Cross-device Adaptive Solution

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 development field of HarmonyOS Next, the responsive layout is a key technology to achieve cross-device adaptation of applications. It enables applications to be like an elegant dancer, showing a perfect posture on the stage of screens with different sizes. Now, let's take an in-depth look at the core concepts of the responsive layout, the application of the grid system, and how to combine it with the adaptive layout to create a more flexible page adaptation solution.

Core Concepts of the Responsive Layout

  1. Breakpoints: Breakpoints are an important foundation of the responsive layout. They take the width of the application window as the starting point and divide the window width into different intervals. For example, common breakpoint value ranges are: XS ([0, 320)vp), sm ([320, 600)vp), md ([600, 840)vp), lg ([840, +∞)vp). Within different breakpoint intervals, developers can implement different page layout effects for the application according to the size differences of the device screens. For example, on mobile devices (corresponding to smaller breakpoint intervals), the page may adopt a single-column layout to adapt to the narrow screen; while on tablets or large-screen devices (corresponding to larger breakpoint intervals), it switches to a multi-column layout to make full use of the screen space to display more content.
  2. Media Queries: Media queries are a powerful tool in the responsive layout. They support listening to a variety of media features, such as window width, portrait and landscape screen status, light and dark mode, device type, and so on. Through media queries, developers can dynamically adjust the styles and layouts of applications according to different device environments and user settings. In actual development, media queries are often used in combination with breakpoints. For example, when the window width changes from one breakpoint to another, the change is monitored through media queries, and the page layout is adjusted synchronously, so that the page can present the best display effect on different devices.
  3. Grid Layout: The grid layout is like a regular "compartment" system built for the page. It helps developers position and layout page elements more efficiently by dividing the space into regular grids. In HarmonyOS Next, the style of the grid is determined by three attributes: Margin (the distance from the left and right edges of the application window or the parent container, which determines the overall width where the content can be displayed), Gutter (the distance between two adjacent Columns, which determines the closeness between the contents), and Columns (the number of columns in the grid, and its value determines the layout complexity of the content). The width of a single Column is automatically calculated by the system in combination with these attributes, and developers do not need to configure it manually. The grid layout combined with breakpoints can achieve flexible layout changes under different window sizes, greatly reducing the design and development costs of adapting to different screen sizes.

Design and Use of the Grid System

In HarmonyOS Next, the grid layout can be easily implemented by using the Grid component. The Grid component includes GridRow and GridCol. By reasonably configuring their attributes, various complex and beautiful page layouts can be created.

  1. Configuring the Number of Columns at Breakpoints: Developers can configure the number of columns occupied by the GridCol component under different screen sizes according to different breakpoints. For example:
@Entry
@Component
struct GridExample {
    @State currentBreakpoint: string = 'unknown'
    build() {
        GridRow({ breakpoints: { value: ['600vp', '700vp', '800vp', '900vp', '1000vp'], reference: BreakpointsReference.WindowSize } }) {
            GridCol({ span: { xs: 12, sm: 6, md: 4, lg: 3, xl: 2, xxl: 2 } }) {
                Text('This is the grid content')
                   .fontSize(20)
                   .backgroundColor('#F1F3F5')
                   .padding(10)
            }
        }
          .onBreakpointChange((currentBreakpoint: string) => {
                this.currentBreakpoint = currentBreakpoint
            })
    }
}
Enter fullscreen mode Exit fullscreen mode

In the above code, according to different breakpoints (xs, sm, md, lg, xl, xxl), the number of columns occupied by the GridCol component will change, so as to achieve layout adjustments under different screen sizes. For example, under the xs breakpoint, the content occupies 12 columns, which is suitable for single-column display on small-screen devices; under the lg breakpoint, it occupies 3 columns, which is suitable for multi-column layout on large-screen devices.

  1. Modifying the Breakpoint Value Range and Reference Object: The grid component supports developers to modify the value range of breakpoints, and they can choose the window width or its own width as the reference object. For example, in some special scenarios, when the size of the application window remains unchanged but the size of a local area changes, it is particularly flexible to use the width of the grid component itself as the reference object to respond to breakpoint changes.
@Entry
@Component
struct GridSelfWidthSample {
    @State currentBreakpoint: string = 'unknown'
    build() {
        SideBarContainer(SideBarContainerType.Embed) {
            // Sidebar, size change range [100vp, 600vp]
            Column() {}.width('100%').backgroundColor('#19000000')
            // Content area, size change range [550vp, 50vp]
            GridRow({ breakpoints: { value: ['100vp', '200vp', '300vp', '400vp', '500vp'], reference: BreakpointsReference.ComponentSize } }) {
                GridCol({ span: { xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 12 } }) {
                    Text(this.currentBreakpoint)
                       .fontSize(50)
                       .fontWeight(FontWeight.Medium)
                }
            }
              .onBreakpointChange((currentBreakpoint: string) => {
                    this.currentBreakpoint = currentBreakpoint
                })
              .width('100%')
        }
          // When the sidebar is dragged to the minimum width, it will not be automatically hidden
          .autoHide(false)
          .sideBarWidth(100)
          // Minimum width of the sidebar
          .minSideBarWidth(100)
          // Maximum width of the sidebar
          .maxSideBarWidth(600)
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the widths of the sidebar and the content area will change according to the user's operation. Using the width of the grid component itself as the reference object, when the width of the content area changes, the breakpoints of the grid will also change accordingly, thus achieving the responsive layout of the local area.

  1. Using Other Attributes of the Grid Component: In addition to the number of columns and breakpoints, the GridCol component also supports attributes such as span, offset, and order. span is used to configure the number of columns occupied by the component under different breakpoints; offset is used to set the number of columns offset relative to the previous grid sub-component; order is used to control the sequence number of the element, and the components are sorted according to the sequence number of the grid sub-components from small to large. For example:
@Entry
@Component
struct GridAdvancedSample {
    private elements: { index: number, color: Resource }[] = [
        { index: 1, color: $r('sys.color.ohos_id_color_palette_aux1') },
        { index: 2, color: $r('sys.color.ohos_id_color_palette_aux2') },
        { index: 3, color: $r('sys.color.ohos_id_color_palette_aux3') }
    ]
    build() {
        GridRow() {
            ForEach(this.elements, (item) => {
                GridCol({ span: { sm: 6, md: 4, lg: 3 }, offset: { sm: 0, md: 2, lg: 1 }, order: { sm: item.index, lg: 4 - item.index } }) {
                    Row() {
                        Text('' + item.index)
                           .fontSize(24)
                           .backgroundColor(item.color)
                           .width('100%')
                           .height(30)
                           .justifyContent(FlexAlign.Center)
                    }
                }
            })
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, by setting the span, offset, and order attributes, the effects of the component occupying different numbers of columns, offset positions, and sorting under different breakpoints are achieved, further enriching the flexibility of the grid layout.

Achieving More Flexible Page Adaptation by Combining with the Adaptive Layout

The adaptive layout and the responsive layout do not exist in isolation. Combining them can bring more powerful cross-device adaptation capabilities to the application. The following is a simple example code to show it:

@Entry
@Component
struct CombinedLayout {
    @State currentBreakpoint: string ='sm'
    build() {
        GridRow({ breakpoints: { value: ['600vp'], reference: BreakpointsReference.WindowSize } }) {
            GridCol({ span: { sm: 12, md: 6 } }) {
                Column() {
                    // Example of adaptive stretching capability
                    Row() {
                        Text('Text with fixed width').width(100).height(50).backgroundColor('#FFD700')
                        Blank().flexGrow(1)
                        Toggle({ type: ToggleType.Switch }).width(36).height(20)
                    }
                    // Example of adaptive wrapping capability
                    Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap }) {
                        ForEach([1, 2, 3, 4, 5, 6], (item) => {
                            Image($r('app.media.image')).width(80).height(80).padding(10)
                        })
                    }
                }
            }
            GridCol({ span: { sm: 12, md: 6 } }) {
                // Responsive layout: display different contents at different breakpoints
                if (this.currentBreakpoint ==='sm') {
                    Text('Content for small screens').fontSize(20).backgroundColor('#ADD8E6')
                } else {
                    Text('Content for large screens').fontSize(20).backgroundColor('#90EE90')
                }
            }
        }
          .onBreakpointChange((breakpoint: string) => {
                this.currentBreakpoint = breakpoint
            })
    }
}
Enter fullscreen mode Exit fullscreen mode

In the above code, the stretching and wrapping capabilities of the adaptive layout are used inside the GridCol component on the left. The stretching capability is reflected in the allocation of the remaining space through the Blank component; the wrapping capability is achieved by the wrap property of the Flex component to automatically wrap the images. The GridCol component on the right demonstrates the responsive layout, displaying different contents according to the breakpoint switch. In this way, by combining the adaptive layout and the responsive layout, the page can not only maintain the reasonable arrangement and adaptive adjustment of elements under different device screen sizes but also display different contents according to the screen size, greatly enhancing the user experience.

The responsive layout technology of HarmonyOS Next provides developers with rich means to achieve cross-device adaptation. By deeply understanding the core concepts of breakpoints, media queries, and grid layout, proficiently using various attributes of the Grid component, and combining with the adaptive layout, developers can create high-quality applications that can be perfectly adapted on various devices. It is hoped that this article can help everyone better use the responsive layout technology in HarmonyOS Next development and create more excellent application interfaces.

Top comments (0)