HarmonyOS NEXT應用開發案例——滑動頁面資訊隱藏與元件位移效果

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

介紹

在很多應用中,向上滑動"我的"頁面,頁面頂部會有如下變化效果:一部分資訊逐漸隱藏,另一部分資訊逐漸顯示,同時一些元件會進行縮放或者位置移動。向下滑動時則相反。

效果圖預覽

image

使用說明
  1. 向上滑動頁面,出現如下變化:使用者名稱/選擇身份/設定圖示/客服圖示逐漸隱藏,使用者頭像尺寸逐漸縮小並向右上平移,頂部"返回"文字後方使用者名稱逐漸顯示。
  2. 滑動到頂部後,向下滑動頁面,出現如下變化:使用者頭像尺寸逐漸變大並向左下平移,頂部"返回"文字後方的使用者名稱逐漸隱藏,原來的使用者名稱/選擇身份/設定圖示/客服圖示逐漸顯示。

實現思路

本例涉及的關鍵特性和實現方案如下:

  1. 將螢幕從上向下分為三部分,第一部分Row元件包含"返回"和初始狀態下隱藏的使用者名稱,第二部分Row包含使用者頭像/使用者名稱/選擇身份/設定/客服,下方其餘部分位第三部分。本例場景的變化體現在第一和第二部分。原始碼參考SlideToHideAndDisplace
Column() {
  Row() {...}
  .padding($r('app.integer.padding_small'))
  .width($r('app.string.size_full'))
  .alignItems(VerticalAlign.Center)
  Row() {...}
  .height($r('app.integer.height_one_hundred'))
  .width($r('app.string.size_full'))
  Scroll() {...}
}
  1. 在第一和第二部分中,使用@State裝飾器裝飾相關的元件屬性,使之與自定義元件的渲染繫結起來,狀態變數改變時,UI會發生對應的渲染改變。使用者頭像的縮放透過改變其width和height屬性值的大小來重新整理,使用者頭像的位移透過改變其margin屬性中的top和left的大小來重新整理。其他一些元件的顯隱變化透過改變其opacity屬性值的大小來重新整理。原始碼參考SlideToHideAndDisplace
  @State userRowOpacity: number = 1;
  @State userImageHeight: number = 50;
  ...

  build() {
    Column() {
      Row() {
        ...
        Text($r('app.string.phone_number'))
          .opacity(this.userNameOpacity) // userNameOpacity控制頂部使用者名稱的透明度
        Blank()
        Text("設定")
          .opacity(this.userNameOpacity) // 設定的文字透明度與頂部使用者名稱相同
        Text("客服")
          .opacity(this.userNameOpacity) // 客服的文字透明度與頂部使用者名稱相同
      }

      Row() {
        Image($r('app.media.batman'))
          .width(this.userImageHeight)
          .height(this.userImageHeight) // userImageHeight控制頭像尺寸
          // userImageMarginTop和userImageMarginLeft控制頭像在父容器內的位置
          .margin({ top: this.userImageMarginTop, left: this.userImageMarginLeft })

        Column() {...}
        .alignItems(HorizontalAlign.Start)
        .opacity(this.userRowOpacity) // 控制Row元件的透明度
      }
      ...
    }
  }
  1. 第三部分頁面滾動透過Scroll元件實現,其中第二欄和第三欄相似,使用@Builder裝飾器封裝了兩個自定義構建函式IconAndDescription和CustomRow,增加程式碼複用。原始碼參考SlideToHideAndDisplace
  // 自定義構建函式,將重複使用的UI元素抽象成一個方法。此處樣式為:上方圖示下方文字
  @Builder
  IconAndDescription(icon: Resource, description: string | Resource, iconSize?: Size, radius?: number) {
    Column() {
      Image(icon)
        .size(iconSize === undefined ? { height: $r('app.integer.icon_default_height'),
          width: $r('app.integer.icon_default_height') } : iconSize)
        .borderRadius(radius)
      Text(description)
        .margin({ top: $r('app.integer.margin_between_icon_and_description') })
    }
  }

  // 自定義構建函式。此處樣式為:在Row元件中橫向排列IconAndDescription
  @Builder
  CustomRow(iconsAndDescriptions: IconAndDescription[]) {
    Row() {
      ForEach(iconsAndDescriptions, (item: IconAndDescription) => {
        this.IconAndDescription(item.icon, item.description)
      })
    }
    .width($r('app.string.size_full'))
    .justifyContent(FlexAlign.SpaceAround)
    .padding($r('app.integer.padding_small'))
    .margin({ top: $r('app.integer.margin_small') })
    .backgroundColor($r('app.color.color_transparent_aa'))
    .borderRadius($r('app.integer.border_radius'))
  }

高效能知識點

本例中Scroll元件繫結onScroll滾動事件回撥,onScroll屬於頻繁回撥,在回撥中需要儘量減少耗時和冗餘操作,例如減少不必要的日誌列印。

工程結構&模組型別

   slidetohideanddisplace                                      // har包
   |---model
   |   |---Util.ets                         				   // 提供測試資料類     
   |---SlideToHideAndDisplace.ets                              // 滑動變化效果實現頁面

模組依賴

不涉及。

參考資料

@State裝飾器

@Builder裝飾器

透明度設定

Scroll

學習鴻蒙開發勢在必行。鴻蒙開發可參考學習文件:https://qr21.cn/FV7h05

相關文章