HarmonyOS NEXT應用開發—自定義檢視實現Tab效果

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

介紹

本示例介紹使用Text、List等元件,新增點選事件onclick,動畫,animationTo實現自定義Tab效果。

效果預覽圖

使用說明

  1. 點選頁籤進行切換,選中態頁簽字型放大加粗,顏色由灰變黑,起到強調作用,同時,底部顏色條橫線位移到當前選中頁簽下方,內容區翻頁到當前選中頁籤對應區域。

實現思路

  1. 頁籤實現:新增onClick方法,記錄點選的index,index變化後,改變頁籤顏色、字型大小,使用animateTo方法實現頁籤切換動畫。 原始碼參考CustomView.ets
Text(title)
  .textAlign(TextAlign.Center)
  .height($r('app.integer.width_and_height_value4'))
  .width(this.titleLengthRadix3 * title.length)
  .fontColor(this.currentIndex == idx ?
            (this.wantGoIndex == idx ? $r('app.color.background_color1'):$r('app.color.background_color2')):
            (this.wantGoIndex == idx ? $r('app.color.background_color1'):$r('app.color.background_color2')))
  .fontSize(this.currentIndex == idx ? $r('app.integer.font_size2') : $r('app.integer.font_size1'))
  .fontWeight(this.currentIndex == idx ? FontWeight.Bold : FontWeight.Normal)
  .onClick(() => {
    if (this.currentIndex != idx) {
      // 記錄點選index
      this.wantGoIndex = idx;
      // 動畫效果
      animateTo({
        duration: Math.abs(idx - this.currentIndex) * this.durationRadix,
        curve: Curve.EaseInOut,
        iterations: this.iterationsDefault,
        playMode: PlayMode.Normal,
        onFinish: () => {
          this.currentIndex = idx;
          this.scroller.scrollToIndex(this.currentIndex, true, ScrollAlign.START);
        }
      }, () => {
        this.transitionX = this.getTransitionX(idx);
      })
    }
  })
  1. 內容區實現:使用List,新增滑動手勢來進行頁面的切換,手勢響應後,使用scrollToIndex方法來實現平滑的滑動到相應index。 原始碼參考CustomView.ets
PanGesture(this.panOption)
  .onActionUpdate((event:GestureEvent) => {
    if (!this.isStartAction) {
      this.isStartAction = true;
      if (event.offsetX < this.judgmentValue) {
        if (this.currentIndex < this.titleArray.length - this.currentIndexRadix) {
          let temIndex: number = this.currentIndex + this.currentIndexRadix;
          this.scroller.scrollToIndex(temIndex, true, ScrollAlign.START);
          this.wantGoIndex = temIndex;
          animateTo({
            duration: Math.abs(temIndex - this.currentIndex) * this.durationRadix,
            curve: Curve.EaseInOut,
            iterations: this.iterationsDefault,
            playMode: PlayMode.Normal,
            onFinish: () => {
              this.currentIndex = temIndex;
            }
          }, () => {
            this.transitionX = this.getTransitionX(temIndex);
          })
        }
      } else {
        if (this.currentIndex > this.judgmentValue) {
          let temIndex: number = this.currentIndex - this.currentIndexRadix;
          this.scroller.scrollToIndex(temIndex, true, ScrollAlign.START);
          this.wantGoIndex = temIndex;
          animateTo({
            duration: Math.abs(temIndex - this.currentIndex) * this.durationRadix,
            curve: Curve.EaseInOut,
            iterations: this.iterationsDefault,
            playMode: PlayMode.Normal,
            onFinish: () => {
              this.currentIndex = temIndex;
            }
          }, () => {
            this.transitionX = this.getTransitionX(temIndex);
          })
        }
      }
    }
  })

高效能知識點

scrollToIndex方法,開啟smooth動效時,會對經過的所有item進行載入和佈局計算,當大量載入item時會導致效能問題

工程結構&模組型別

customview                                       // har型別
|---view
|   |---CustomView.ets                           // 檢視層-自定義檢視實現Tab效果

模組依賴

utils

參考資料

PanGesture 事件

animateTo 顯示動畫

scrollToIndex 方法

寫在最後

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

相關文章