HarmonyOS Three-Foldable App Development Treasure: Official Case Study and Practical Code
Hello everyone! Today, while browsing the HarmonyOS documentation, I discovered a super valuable resource—the official three-foldable development case! I used to think multi-device adaptation was complicated, but HarmonyOS already has a comprehensive solution. Let’s get straight to the point and dive into three-foldable screen development with code examples!
🚀 Three States of the Three-Foldable and Breakpoint Adaptation
Three-foldable phones (like the Mate XT) have three core states, each corresponding to a different layout strategy:
-
Single Screen (F State): Standard phone layout, breakpoint
sm
-
Dual Screen (M State): Similar to large foldable unfolded state, breakpoint
md
-
Triple Screen (G State): Tablet layout, breakpoint
lg
Key Tip: Use breakpoints instead of device type to determine layout, ensuring code universality:
// Switch Tabs position based on breakpoint (bottom → sidebar)
@StorageLink('currentWidthBreakpoint') currentWidthBreakpoint: string = 'lg';
build() {
Tabs({
barPosition: this.currentWidthBreakpoint === 'lg' ?
BarPosition.Start : BarPosition.End // Sidebar for lg, bottom for others
}) {
...
}
.vertical(this.currentWidthBreakpoint === 'lg') // Vertical for lg
}
📌 Why use breakpoints?
Avoid using deviceType == 'tablet'
for judgment. The G state of a three-foldable and a tablet layout should be consistent, but device types differ!
🖼️ Typical Layout Scenarios in Practice
Scenario 1: Sidebar Navigation (Dynamic Migration from F to G State)
Effect: Bottom navigation bar on small screens, switches to left sidebar on large screens (≥840vp).
Key code points:
// 1. Listen for window changes (EntryAbility.ets)
onWindowStageCreate(windowStage: window.WindowStage) {
windowStage.getMainWindow().then((win: window.Window) => {
win.on('windowSizeChange', (size: window.Size) => {
AppStorage.setOrCreate('windowWidth', size.width); // Store window width
});
});
}
// 2. Dynamically adjust navigation bar on page (Home.ets)
@StorageProp('windowWidth') winWidth: number = 0;
build() {
if (this.winWidth >= 840) { // Reaches lg breakpoint
Navigation() {
SideBar() { ... } // Left navigation
ContentArea() { ... }
}
} else {
BottomTabs() { ... } // Bottom navigation
}
}
Scenario 2: Waterfall Image Adaptive Columns
Problem: 2 columns on small screens, 3 columns on large screens with adjusted aspect ratio.
Code solution:
// Set WaterFlow columns based on breakpoint
@StorageLink('currentBreakpoint') breakpoint: string;
build() {
WaterFlow() {
ForEach(this.imageList, (item) => {
Image(item.url)
.aspectRatio(1.5) // Fixed aspect ratio to prevent distortion
})
}
.columnsTemplate(this.breakpoint === 'lg' ?
'1fr 1fr 1fr' : '1fr 1fr' // 3 columns for lg, 2 for others
)
}
Scenario 3: Carousel Extended Effect on Large Screens
G State Exclusive: Partially reveal content on both sides for enhanced visual extension.
Key API: prevMargin
+ nextMargin
Swiper() {
ForEach(this.bannerList, (item) => {
Image(item.url)
})
}
.displayCount(5) // Show 5 images in G state
.prevMargin(40) // Reveal 40px on the left
.nextMargin(40) // Reveal 40px on the right
.itemSpace(10) // Image spacing
Scenario 4: Hover Camera (Special Interaction in Half-Fold State)
Effect: Trigger hover shooting mode when the screen is half-folded.
Code focus: Listen for fold state + lock landscape orientation
// Listen for fold status changes
display.on('foldStatus', (status: display.FoldStatus) => {
if (status === display.FoldStatus.FOLD_STATUS_HALF_FOLDED) {
this.isHalfFolded = true; // Enter hover state
window.getLastWindow().then(win => {
win.setPreferredOrientation(window.Orientation.LANDSCAPE); // Force landscape
});
}
});
// UI exclusive to hover state
build() {
if (this.isHalfFolded) {
SuspendedCameraView() // Hover shooting component
}
}
⚠️ Pitfall Guide
- Rotation Failure Issue Wrong approach: Use fold state to determine rotation (G state of three-foldable ≠ unfolded state of large foldable). Correct solution: Control with window aspect ratio:
// Set camera preview area based on aspect ratio
if (widthBp === 'md' && heightBp === 'md') {
surfaceRect = { width: winWidth, height: winWidth * 0.75 }; // 4:3 ratio
}
-
Layout Stretching Issue
Must-add property:
.aspectRatio()
to ensure image/video proportions:
GridItem() {
VideoPlayer().aspectRatio(16/9) // Force 16:9
}
💎 Summary
The core of HarmonyOS's three-foldable adaptation solution can be summarized as:
✅ Breakpoint-driven layout: sm/md/lg covers all states
✅ Dynamic component properties: Tabs/WaterFlow/Swiper adjust parameters based on breakpoints
✅ Special state listening: Hover state triggered by foldStatus
For those developing foldable screens, start using these now! If you have any questions, feel free to discuss in the comments. More hidden HarmonyOS tips coming next time! ✨
Top comments (0)