Hong Mong 5 Development Treasure Case Sharing More Than One Breakpoint Development Practice

????
【HarmonyOS Advanced Development Practice】In-depth Analysis of Six Core Cases to Master Multi-terminal Adaptation!
???? Case 4: Dynamic Grid Layout (E-commerce Product List)
Application Scenario: Product display differences on phone/tablet
Pain Point Analysis: Single column on phone → multi-column on tablet, need to intelligently calculate the number of items displayed
@Component
struct GoodsGrid {
@StorageLink('currentWidthBreakpoint') bp: string
build() {
Grid() {
ForEach(goodsList, (item) => {
GridItem() {
GoodsItem(item) // Product card component
}
})
}
.columnsTemplate(this.getColumnsTemplate())
.rowsTemplate(this.getRowsTemplate())
}
// Dynamic column calculation
private getColumnsTemplate(): string {
switch(this.bp) {
case 'sm': return '1fr'; // Single column on phone
case 'md': return '1fr 1fr'; // Dual column on foldable
case 'lg': return '1fr 1fr 1fr'; // Triple column on tablet
default: return '1fr';
}
}
// Dynamic row spacing
private getRowsTemplate(): string {
return this.bp === 'sm' ? '56vp' : '72vp'; // Larger spacing on large screens
}
}
Effect Comparison:
- Phone (sm): Waterfall single column, compact spacing
- Foldable (md): Dual column, adaptive images
- Tablet (lg): Triple column, additional product parameters
????️ Case 5: Adaptive Navigation Bar (Cross-device Menu)
Application Scenario: Sidebar on Pad landscape, hamburger menu on phone
Key Technology: @Watch listener + conditional rendering
@Entry
struct MainPage {
@State isCollapsed: boolean = false
@StorageLink('currentWidthBreakpoint') bp: string
// Automatically triggered on breakpoint change
@Watch('bp')
onBpChange() {
this.isCollapsed = this.bp === 'sm'; // Auto collapse on small screen
}
build() {
Row() {
// Sidebar (shown on large screens)
if(!this.isCollapsed) {
Column() {
MenuItems() // Navigation menu component
}
.width(240)
.backgroundColor('#F5F5F5')
}
// Main content area
Column() {
Header({
showMenuBtn: this.isCollapsed // Show menu button on small screen
})
Content()
}
}
}
}
Interaction Logic:
- Width ≥ 840vp (lg): Fixed 240vp left navigation bar
- 320vp ≤ Width < 840vp (md): Collapsed as floating sidebar
- Width < 320vp (xs): Hide navigation, show hamburger menu at top
???? Case 6: Reader Split Mode (Document App)
Special Requirement: Special layout for half-open foldable
Core Code:
@Component
struct ReaderLayout {
@StorageLink('currentHeightBreakpoint') hBp: string
build() {
Flex({ direction: FlexDirection.Row }) {
// Left catalog (show when aspect ratio > 1.2)
if(this.hBp === 'lg') {
Column() {
ChapterList() // Catalog component
}
.width('30%')
}
// Main reading area
Scroll() {
TextContent() // Text component
}
.flexGrow(1)
// Right notes (shown on square screen)
if(this.hBp === 'md') {
Column() {
NotesPanel() // Notes panel
}
.width(280)
}
}
}
}
Device Adaptation:
- Phone portrait (hBp=lg): Single column reading, floating catalog at bottom
- Foldable half-open (hBp=md): Main text + right notes dual column
- Tablet landscape (hBp=sm): Three columns (catalog + text + annotation)
???? Case 7: Video Player Multi-form Adaptation
Complex Scenario: Fullscreen/split-screen/picture-in-picture mode
Key Technology Points: Window state monitoring + dynamic styles
@Component
struct VideoPlayer {
@StorageLink('currentWidthBreakpoint') bp: string
@State isFullscreen: boolean = false
build() {
Stack() {
VideoComponent() // Core player
.aspectRatio(this.getVideoRatio()) // Dynamic ratio
// Fullscreen mode controls
if(this.isFullscreen) {
FullscreenControls()
}
}
.onClick(() => {
if(this.bp === 'sm') { // Tap to toggle fullscreen on small screen
this.toggleFullscreen();
}
})
}
// Set video ratio by breakpoint
private getVideoRatio(): number {
switch(this.bp) {
case 'sm': return 16/9; // 16:9 on phone
case 'md': return 21/9; // 21:9 on foldable
case 'lg': return this.isFullscreen ? 16/9 : 4/3; // Tablet adaptation
default: return 16/9;
}
}
private toggleFullscreen() {
// Fullscreen logic (omitted)
}
}
Key Adaptation Strategies:
- Phone portrait: Default 16:9, tap to fullscreen
- Foldable unfolded: 21:9 cinema ratio
- Tablet split-screen: 4:3 for multitasking layout
???? Case 8: Dynamic Layout for Data Dashboard
Business Requirement: Multi-terminal data visualization from smart watch to smart screen
Code Snippet:
@Entry
struct Dashboard {
@StorageLink('currentWidthBreakpoint') bp: string
build() {
GridRow({ columns: this.getGridColumns() }) {
GridCol({ span: { xs:12, sm:6, md:4, lg:3 } }) {
DataCard('Sales', '¥12.34M') // Data card
}
GridCol({ span: { xs:12, sm:6, md:8, lg:6 } }) {
ChartComponent() // Visualization chart
}
}
}
private getGridColumns(): number | GridRowColumnOption {
return {
xs: 4, // 4 columns for watch (80vp each)
sm: 8, // 8 columns for phone
md: 12, // 12 columns for foldable
lg: 24 // 24 columns for large screen
}
}
}
Layout Strategy:
- Watch (xs): Key metrics stacked in single column
- Phone (sm): Left-right block display
- Smart screen (lg): 24-column fine layout, multi-chart linkage
????️ Case 9: Automatic Form Layout Optimization
Typical Scenario: Login screen portrait/landscape adaptation
Innovative Solution: Mixed grid + flex layout
@Component
struct LoginForm {
@StorageLink('currentHeightBreakpoint') hBp: string
build() {
Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center }) {
Image($r('app.media.logo'))
.height(this.hBp === 'sm' ? 80 : 120) // Shrink logo in landscape
FormLayout() {
TextInput().placeholder('Account')
TextInput().placeholder('Password')
}
.layoutType(this.hBp === 'sm' ? LayoutType.Grid : LayoutType.List)
Button('Login')
.width(this.hBp === 'sm' ? '60%' : '40%')
}
.padding(this.getFormPadding())
}
private getFormPadding(): Padding {
return {
top: this.hBp === 'lg' ? 40 : 20, // More top padding in portrait
bottom: 20,
left: this.hBp === 'sm' ? 10 : 30, // Compact layout in landscape
right: this.hBp === 'sm' ? 10 : 30
}
}
}
Layout Changes:
- Portrait (hBp=lg): List arrangement, large spacing
- Landscape (hBp=sm): Compact grid layout, adaptive width
???? Developer Tips (Pitfall Avoidance Guide)
- Breakpoint Coverage Strategy
// Wrong: Missed breakpoint range
if(bp === 'sm') {...}
else {...}
// Correct: Full coverage
switch(bp) {
case 'xs':...
case 'sm':...
case 'md':...
case 'lg':...
default:...
}
- Golden Rule for Unit Selection
- Text:
fp
(font pixel, auto adapts to system scaling) - Layout:
vp
(virtual pixel, screen density independent) - Media resources:
px
(physical pixel, ensures clarity) - Multi-device Debugging Tips
# Start multiple devices at once via command line
hdc shell snapshot_demo -s 1080x2340 -d "Phone"
hdc shell snapshot_demo -s 2200x2480 -d "Foldable"
???? Ultimate Adaptation Architecture
├── resources
│ ├── breakpoints
│ │ ├── phone.ets # Phone-specific layout
│ │ ├── tablet.ets # Tablet layout strategy
│ │ └── foldable.ets # Foldable adaptation
├── utils
│ ├── BreakpointManager.ets # Breakpoint state management
│ └── LayoutCalculator.ets # Dynamic layout calculation
└── components
├── AdaptiveContainer.ets # Adaptive container
└── ResponsiveImage.ets # Responsive image component
After mastering these cases, you will be able to flexibly combine these patterns like building blocks when facing complex multi-terminal adaptation needs. If you encounter particularly tricky adaptation problems, feel free to leave a comment and let's discuss solutions together! ????
Popular Products
-
Yoga Ball Kit
$55.99$38.78 -
Electronic Bidet Toilet Seat
$836.99$500.78 -
Adjustable Shower Chair Seat
$121.99$84.78 -
Cordless Car Vacuum
$117.99$81.78 -
Adjustable Plug-in LED Night Light
$93.99$64.78