HarmonyOS IM System Practice: One Development, Multi-Endpoint Deployment
Background Introduction
Instant Messaging (IM) has become an indispensable part of modern applications, playing a crucial role in enhancing user experience, improving business efficiency, strengthening customer service, and driving business growth. From the live streaming apps developed at the start of my career to the current housing platform applications, IM has always played a vital role. With the rise of the HarmonyOS and the maturity of its ecosystem, many manufacturers are adapting to HarmonyOS Next. As an early adopter, I hope to explore new ways to implement IM scenarios through the new features of HarmonyOS.
This article shares practical implementations of "One Development, Multi-Endpoint Deployment" (referred to as "One-Many") in IM systems.
1. What is One Development, Multi-Endpoint Deployment?
First, let's look at the official definition of "One Development, Multi-Endpoint Deployment" (abbreviated as "One-Many"):
One codebase, one development and release process, multi-endpoint deployment on demand.
Goal: Enable developers to efficiently develop applications supporting multiple device forms, ensuring compatibility with different devices while providing distributed experiences such as cross-device flow, migration, and collaboration.
To achieve the "One-Many" goal, two fundamental issues need to be solved:
- How to adapt to devices with different sizes and display capabilities;
- How to兼容 functions for devices with different system capabilities (e.g., TVs without cameras or watches without microphones).
In summary: "One-Many" solves page adaptation and functional compatibility issues for different devices with a single codebase. This article focuses on page adaptation.
After understanding the definition of One-Many, let's examine the pain points of device adaptation in the past.
In the early days of my career, I developed a live streaming app for two platforms: Windows and Android, each implemented with native technologies. This approach was inefficient. Later, the Windows platform switched to the QT framework for cross-platform development. However, QT increased the package size, and due to the different screen sizes of Windows and Android, the UI layouts for the two platforms had to be completely different. As a result, only business logic could be shared across platforms, while UI development remained platform-specific.
Popular frameworks like Flutter face the same challenge: due to differing UI layouts, the UI layer must be adapted to platforms with different screen sizes.
Before HarmonyOS Next, there was no complete solution for achieving satisfactory UI effects with a single codebase—separate adaptations were necessary. HarmonyOS's page-level One-Many capability completely solves this problem.
2. What Can One-Many Bring to IM?
In IM scenarios, take Feishu's chat function as an example: on PC, the conversation list and chat page are arranged side-by-side:
On mobile devices with smaller screens, the conversation list and chat page become separate pages:
Based on HarmonyOS Next's page-level One-Many capability, we can use a single codebase to implement the above chat interface adaptations.
3. Introduction to HarmonyOS One-Many
Let's think: how would we design a system to achieve the above capabilities without considering HarmonyOS?
First, device-independent pixels (similar to dp units in Android) are essential to adapt content size to different device sizes.
Second, the system needs to support using different UIs for devices with varying screen sizes.
HarmonyOS ArkUI provides two layout capabilities to solve these problems:
- Adaptive Layout: When the external container size changes, page elements automatically adjust based on relative relationships (e.g., proportion, fixed aspect ratio, display priority) to adapt to the container. For example, on large screens, the conversation list and chat notifications are displayed side-by-side, while on small screens, they are displayed separately. ArkTS offers seven adaptive layout capabilities: stretching, equal distribution, proportion, scaling, extension, hiding, and wrapping.
- Responsive Layout: When the external container size changes significantly (e.g., foldable phone switching from 400vp to 1000vp width), elements adjust based on breakpoints, grids, or specific features (e.g., screen orientation, window size) to adapt to the container. ArkTS provides three responsive layout capabilities: breakpoints, media queries, and grid layout.
3.1 Adaptive Layout
ArkUI abstracts seven adaptive layout capabilities:
-
Stretching: When the container size changes, the increased or decreased space is fully allocated to specified areas within the container. Achieved via
flexGrow
andflexShrink
in Flex layout. -
Equal Distribution: When the container size changes, the space is evenly distributed to all empty areas within the container. Achieved by setting
justifyContent
toFlexAlign.SpaceEvenly
for Row, Column, or Flex components (e.g., TAB layouts on home pages). -
Proportion: The width or height of child components changes with the container according to a preset ratio. Implemented by setting child component width/height as a percentage of the parent or using the
layoutWeight
property. -
Scaling: The width and height of child components change with the container according to a preset ratio while maintaining the aspect ratio. Achieved via the
aspectRatio
property in layout constraints. - Extension: Child components in the container are displayed or hidden in their order within the list as the container size changes. Implemented via List components or Scroll components with Row/Column.
-
Hiding: Child components in the container are displayed or hidden based on preset display priorities. Components with the same priority are displayed or hidden simultaneously. Achieved via the
displayPriority
property in layout constraints. -
Wrapping: When the container size is insufficient to display all content, the layout automatically wraps to the next line. Achieved by setting
wrap
toFlexWrap.Wrap
in Flex components.
3.2 Responsive Layout
Adaptive layouts ensure normal display within a certain window size range. However, when the window size changes significantly (e.g., a foldable phone switching from 400vp to 1000vp width), relying solely on adaptive layout may cause issues like abnormal image scaling or excessive white space (e.g., a feed stream that looks sparse with two columns on a large screen and should display four columns for better aesthetics). In such cases, responsive layout capabilities are needed to adjust the page structure.
Responsive layout refers to the ability of page elements to automatically adapt to changes in the external container based on specific features (e.g., window width, screen orientation). The most commonly used feature in responsive layout is window width, which is divided into different ranges (called "breakpoints" in ArkUI). When the window width crosses a breakpoint, the page layout is adjusted (e.g., changing from a single column to two or three columns) for optimal display.
The system currently provides three responsive layout capabilities:
- Breakpoints: Divide window width into ranges (breakpoints), listen for window size changes, and adjust the page layout when a breakpoint is crossed.
- Media Queries: Listen for multiple media features (window width, orientation, light/dark mode, device type, etc.) and adjust the page layout when features change.
- Grid Layout: Divides the area into regular columns, allowing layout adjustments by modifying grid parameters and the number of columns occupied by child components at different breakpoints.
4. Practical Implementation of One-Many in IM Systems
4.1 Adapting to Screen Size Changes
Grid Layout
Grid layout provides a regular structure for layouts, solving dynamic layout problems across multi-size devices and ensuring layout consistency. For example, on small screens, the "My Page" section fills the screen, while on large screens, we may want留白 on both sides—achievable via grid layout. Grid layout parameters determine how the screen is divided into columns and can set different spacing for different screens.
ArkUI provides GridRow
and GridCol
to implement grid layouts, which can be used to listen for breakpoints.
Sample code:
build() {
GridRow({
columns: {
sm: 4,
md: 12,
lg: 12
}
}) {
GridCol({ span: {
sm: 4,
md: 12,
lg: 12
} }) {
Column() {
Home()
}
.width('100%')
.height('100%')
}
.height('100%')
.width('100%')
}
.onBreakpointChange((breakPoints) => {
this.currentBreakpoint = breakPoints;
})
}
4.2 Displaying Different Content on Different Screens
Navigation Component
How to display different pages on different screens? For example, showing only the conversation list on mobile devices and a split view (left list, right details) on foldables or PCs.
ArkUI provides the Navigation
component, which serves as the root container for pages and supports three display modes: single-page, split-view, and adaptive. Suitable for in-module page switching in One-Many scenarios, it enables smooth transition effects through component-level routing and offers various title bar styles for better title-content linkage. In One-Many scenarios, the Navigation component automatically adapts to window size, switching to split-view on larger screens.
Key properties used:
-
navBarWidth
: Width of the navigation bar, effective only in split-view mode. -
navDestination
: CreatesNavDestination
components to build different content pages based on strings (e.g., building a chat page for selected conversations or a blank page for unselected ones). -
mode
: Display mode of the navigation bar. Default isNavigationMode.Auto
; useNavigationMode.Split
for large screens andNavigationMode.Stack
for mobile.
Sample code:
build() {
Column() {
Navigation(this.pageInfo) {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center }) {
ConversationList({
currentConversationUserName: $currentConversationUserName,
currentContactUserName: $currentContactUserName
})
.flexGrow(BaseConstants.FLEX_GROW_ONE)
.width(BaseConstants.FULL_WIDTH)
}
.hideTitleBar(true)
.hideToolBar(true)
.navBarWidth(this.currentBreakpoint === BreakpointConstants.BREAKPOINT_LG ? HomeConstants.NAVIGATION_NAV_BAR_WIDTH_LG :
HomeConstants.NAVIGATION_NAV_BAR_WIDTH_MD)
.navDestination(this.PageMap)
.mode(this.currentBreakpoint === BreakpointConstants.BREAKPOINT_SM ? NavigationMode.Stack : NavigationMode.Split)
.width(BaseConstants.FULL_WIDTH)
}
}
@Builder
PageMap(name: string) {
if (name === 'ConversationDetail') {
ConversationDetail({ currentConversationUserName: this.currentConversationUserName, currentFeatureIndex: 1 });
} else if (name === 'ConversationDetailNone') {
ConversationDetailNone();
} else {
ConversationDetailNone();
}
}
5. Summary
This article introduces HarmonyOS's page-level One-Many features and capabilities through IM chat adaptation. ArkUI truly enables one codebase for multi-endpoint deployment, solving the last mile of cross-platform development. We look forward to the improvement of the HarmonyOS ecosystem and the early experience of smooth and convenient new products.
Top comments (0)