Join our FREE personalized newsletter for news, trends, and insights that matter to everyone in America

Newsletter
New

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

Card image cap

????
【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:

  1. Phone portrait: Default 16:9, tap to fullscreen
  2. Foldable unfolded: 21:9 cinema ratio
  3. 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)

  1. 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:...  
}  
  1. Golden Rule for Unit Selection
  2. Text: fp (font pixel, auto adapts to system scaling)
  3. Layout: vp (virtual pixel, screen density independent)
  4. Media resources: px (physical pixel, ensures clarity)
  5. 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! ????