HarmonyOS NEXT應用開發實戰—元件堆疊

生活就是这么怪發表於2024-04-23

介紹

本示例介紹運用Stack元件以構建多層次堆疊的視覺效果。透過繫結Scroll元件的onScroll滾動事件回撥函式,精準捕獲滾動動作的發生。當滾動時,實時地調節元件的透明度、高度等屬性,從而成功實現了巢狀滾動效果、透明度動態變化以及平滑的元件切換。

效果圖預覽

image

使用說明

  1. 載入完成後顯示整個介面,超過一屏可以上下滑動可見堆疊效果。

實現思路

  1. 在向上滑動過程中觀察到頭部元件是處於層級底部,而其他元件覆蓋在其上方,為此,選擇Stack元件來獲取堆疊效果。
Stack({ alignContent: Alignment.Top }) {
  Scroll(this.scroller) {
    ...
  }
}
  1. 在頂部的可滾動區域,透過使用Scroll元件來獲取堆疊效果。
Scroll(this.scroller) {
  Column() {
    ...
  }
}
  1. 實現滾動過程中動態調整文字框高度的功能時,運用Scroll元件滾動事件回撥函式onScroll在滾動時修改文字框的高度及元件的透明度。
.onScroll(() => {
  let yOffset: number = this.scroller2.currentOffset().yOffset;
  this.Height2 = this.Height2_raw - yOffset * 0.5;
  // 根據yOffset的偏移量來設定IconList2的透明度,當偏移量大於等於IconList2原始高度就是透明的。
  if (1 - yOffset / this.IconList2_raw >= 0) {
    this.Opacity2 = 1 - yOffset / this.IconList2_raw; // IconList2的透明度
  } else {
    this.Opacity2 = 0;
  }
  // 巧妙利用IconList2的透明度的值Opacity2來設定IconList2的縮放。
  this.ratio = this.Opacity2;
  // 根據yOffset的偏移量來設定IconList1的透明度和IconList3的間距,當偏移量大於等於IconList1原始高度就是透明的同時IconList3的間距也是最小的。
  if (1 - yOffset / this.IconList1_raw > 0) {
    this.isChange = false;
    this.Opacity = 1 - yOffset / this.IconList1_raw; // IconList1的透明度
    this.marginSpace = this.maxMarginSpace; // IconList3預設間距
  } else {
    this.isChange = true;
    this.Opacity = (yOffset - this.IconList1_raw) / this.maxMarginSpace; // IconList1的透明度
    this.marginSpace = this.IconList3_raw - yOffset > this.minmarginSpace ?
    (this.IconList3_raw - yOffset) : this.minmarginSpace; // IconList3的間距
  }
})
  1. 存在多層巢狀滾動的情況時,應該先滾動父元件,再滾動自身。只需要在內層的Scroll元件的屬性nestedScroll設定向前向後兩個方向上的巢狀滾動模式,實現與父元件的滾動聯動。
Scroll(this.scroller2){
  ...
}
.width('100%')
.scrollBar(BarState.Off)
.nestedScroll({
  scrollForward: NestedScrollMode.PARENT_FIRST, // 可滾動元件往末尾端滾動時的巢狀滾動選項,父元件先滾動,父元件滾動到邊緣以後自身滾動。
  scrollBackward: NestedScrollMode.SELF_FIRST // 可滾動元件往起始端滾動時的巢狀滾動選項,自身先滾動,自身滾動到邊緣以後父元件滾動。
})
  1. 在商品列表區域,採用瀑布流(WaterFlow)容器進行佈局,將商品資訊動態分佈並分成兩列呈現,每列商品自上而下排列。
WaterFlow() {
  LazyForEach(this.productData, (item: ProductDataModel) => {
    FlowItem() {
      ...
  }, (item: ProductDataModel) => item.id.toString())
}
.nestedScroll({
  scrollForward: NestedScrollMode.PARENT_FIRST,
  scrollBackward: NestedScrollMode.SELF_FIRST
})
.columnsTemplate("1fr 1fr")
}

高效能知識點

本示例使用了LazyForEach進行資料懶載入,WaterFlow佈局時會根據可視區域按需建立FlowItem元件,並在FlowItem滑出可視區域外時銷燬以降低記憶體佔用。 本例中Scroll元件繫結onScroll滾動事件回撥,onScroll屬於頻繁回撥,在回撥中需要儘量減少耗時和冗餘操作,例如減少不必要的日誌列印。

工程結構&模組型別

componentstack                                   // har型別
|---mock
|   |---IconMock.ets                             // 本地資料來源 
|---model
|   |---DataSource.ets                           // 列表資料模型
|   |---IconModel.ets                            // 資料型別定義 
|---view
|   |---ComponentStack.ets                       // 元件堆疊主頁面 
|   |---IconView.ets                             // 按鈕快捷入口自定義元件 
|   |---ProductList.ets                          // 商品列表自定義元件

模組依賴

本例項依賴common模組來實現資源的呼叫。 還需要依賴EntryAbility.ets模組

參考資料

WaterFlow

Stack

Z序控制

元件可見區域變化事件

寫在最後

  • 如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
  • 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
  • 關注小編,同時可以期待後續文章ing🚀,不定期分享原創知識。
  • 想要獲取更多完整鴻蒙最新VIP學習資源,請移步前往小編:https://qr21.cn/FV7h05

相關文章