DEV Community

ι™ˆζ¨
ι™ˆζ¨

Posted on

Hong Mong 5 Development Treasure Case Sharing Experience Smooth Home Info Stream

🌟 HarmonyOS News Home Page Development Guide: Smooth Animation + Lazy Loading Practice

Hey HarmonyOS Developers! Today I'm sharing a super practical solution for developing a news-style homepage in HarmonyOS. I've dug out a treasure case from the official docs! From smooth tab switching animations to silky lazy loading lists, I'll walk you through building a high-performance news homepageπŸ‘‡


πŸš€ Overall Scene Effect

User Operation Flow:

  1. Get location permission β†’ 2. Tap the top address bar to switch city β†’ 3. Swipe/click Tab to switch news category β†’ 4. Pull down to refresh + pull up to load more β†’ 5. One-click back to top (Actual effect is smoother than GIF)

Performance Highlights:

  • Tab switch response delay only 51ms
  • Pull-down refresh response 153ms, pull-up load 150ms
  • Bottom navigation Lottie animation frame rate stable at 60FPS

πŸ”₯ Core Module Code Practice

1️⃣ Navigation Bar Switch Animation (51ms Response Secret)

Problem: Using<font style="color:rgba(0, 0, 0, 0.9);background-color:rgb(252, 252, 252);">onChange</font>event causes animation delay!

Correct Solution: Use<font style="color:rgba(0, 0, 0, 0.9);background-color:rgb(252, 252, 252);">onAnimationStart</font>to trigger animation synchronously

// TabBar.ets  
build() {  
  Tabs({ barPosition: BarPosition.Start }) {  
    ForEach(this.tabBarArray, (item) => {  
      TabContent() { /* News List */ }  
    })  
  }  
  .onAnimationStart((_, targetIndex) => {  
    this.currentIndex = targetIndex; // Key! Sync tab state in real time  
    playTabAnimation(); // Custom animation function  
  })  
}
Enter fullscreen mode Exit fullscreen mode

πŸ’‘ Pitfall Guide:

  • Avoid using<font style="color:rgba(0, 0, 0, 0.4);background-color:rgb(252, 252, 252);">onClick</font>(conflicts with swipe)
  • Animation resources should be less than 30KB (ensure loading speed)

2️⃣ Bottom Navigation Lottie Animation (349ms Ultimate Experience)

Three Steps to Achieve Dynamic Icons:

Step 1: Install animation library

ohpm install @ohos/lottie
Enter fullscreen mode Exit fullscreen mode

Step 2: Encapsulate animation controller

// Home.ets  
import lottie from '@ohos/lottie';  

private lottieController() {  
  lottie.stop(); // Stop previous animation  
  lottie.play(this.tabOptions[this.currentIndex].name); // Play current tab animation  
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Render animation in Canvas

Canvas(this.canvasContext)  
  .onReady(() => {  
    lottie.loadAnimation({  
      container: this.canvasContext,  
      path: 'common/lottie_home.json', // Animation resource path  
      autoplay: false  
    });  
  })
Enter fullscreen mode Exit fullscreen mode

🌟 Tips:

  • Use<font style="color:rgba(0, 0, 0, 0.4);background-color:rgb(252, 252, 252);">RenderingContextSettings(true)</font>to enable anti-aliasing
  • Put animation JSON files in<font style="color:rgba(0, 0, 0, 0.4);background-color:rgb(252, 252, 252);">entry/src/main/resources/rawfile</font>directory

3️⃣ Pull Down to Refresh & Pull Up to Load (150ms Response)

Awesome Third-Party Library:<font style="color:rgba(0, 0, 0, 0.9);background-color:rgb(252, 252, 252);">pullToRefresh</font>

// Install dependency  
ohpm install @ohos/pulltorefresh  

// Usage example  
PullToRefresh({  
  data: $newsData, // Data source  
  scroller: this.scroller, // Scroll controller  
  onRefresh: () => {  
    return new Promise((resolve) => {  
      fetchNewData(); // Simulate network request  
      setTimeout(resolve, 500);  
    });  
  },  
  onLoadMore: () => { /* Similar implementation */ }  
}) {  
  LazyForEach(this.newsData, (item) => {  
    NewsItem({ data: item }) // Encapsulated news item component  
  })  
}
Enter fullscreen mode Exit fullscreen mode

⚠️ Key Configuration:

<font style="color:rgba(0, 0, 0, 0.4);background-color:rgb(252, 252, 252);">List</font>component must set <font style="color:rgba(0, 0, 0, 0.4);background-color:rgb(252, 252, 252);">edgeEffect: EdgeEffect.None</font> to avoid native scroll conflict


4️⃣ Homepage Feed Lazy Loading (Smooth with Tens of Thousands of Data)

Performance Core:<font style="color:rgba(0, 0, 0, 0.9);background-color:rgb(252, 252, 252);">LazyForEach</font> + Pagination Loading

List() {  
  LazyForEach(this.newsDataSource, (item: NewsData) => {  
    ListItem() {  
      NewsItem({  
        title: item.title,  
        image: item.image,  
        // ...  
      })  
    }  
  }, item => item.id.toString())  
}  
.onScrollIndex((first, last) => {  
  if (last > this.data.length - 5) {  
    loadMoreData(); // Load more when reaching the bottom  
  }  
})
Enter fullscreen mode Exit fullscreen mode

πŸš€ Optimization Points:

  • Use<font style="color:rgba(0, 0, 0, 0.4);background-color:rgb(252, 252, 252);">AsyncImage</font>for async image loading
  • Use<font style="color:rgba(0, 0, 0, 0.4);background-color:rgb(252, 252, 252);">TextOptimization</font>to enable font cache for text

5️⃣ Address Selection Page (Accurate Positioning + Fast Search)

Dual Approach:

  • Location Service: Get real-time geographic info
  • AlphabetIndexer: City index navigation
// Get current location  
geoLocationManager.getCurrentLocation((err, location) => {  
  if (location) {  
    geoLocationManager.getAddressesFromLocation({  
      latitude: location.latitude,  
      longitude: location.longitude  
    }, (err, address) => {  
      AppStorage.setOrCreate('currentCity', address[0].locality);  
    });  
  }  
});  

// City index list  
AlphabetIndexer({ arrayValue: ['A','B','C'...] })  
  .onSelect((index) => {  
    this.scroller.scrollToIndex(index); // Jump to corresponding letter  
  })
Enter fullscreen mode Exit fullscreen mode

πŸ” Permission Configuration:

Add in<font style="color:rgba(0, 0, 0, 0.4);background-color:rgb(252, 252, 252);">module.json5</font>:

"requestPermissions": [  
  "ohos.permission.LOCATION",  
  "ohos.permission.APPROXIMATELY_LOCATION"  
]
Enter fullscreen mode Exit fullscreen mode

πŸ’Ž Summary

This news homepage solution perfectly integrates:

βœ… Performance Optimization: LazyForEach lazy loading + animation priority control

βœ… Experience Upgrade: Delicate Lottie animation + gesture interaction feedback

βœ… Development Efficiency: Third-party components (pullToRefresh/lottie) quick integration

One last word: I'll bring more practical cases next time! If you find it useful, remember to like and bookmark🌟 β†’ See you in the comments if you have questionsπŸ‘‡

Top comments (0)