鴻蒙HarmonyOS實戰-ArkUI元件(Tabs)

蜀道山QAQ發表於2024-04-15

🚀一、Tabs

Tabs元件是一種常見的使用者介面(UI)元件,它是一個可以容納多個選項卡的容器元件。每個選項卡通常包含一個皮膚和一個標籤,使用者可以透過點選標籤來切換皮膚。Tabs元件通常用於展示多個相關但又不需要同時展示的資料集合或功能集合,以提高頁面的可維護性和可用性。

Tabs元件的主要功能包括:

  1. 切換選項卡:使用者可以透過點選標籤來切換顯示皮膚。
  2. 啟用狀態:當前選中的標籤會呈現啟用狀態,以便使用者清楚地知道他們當前所在的選項卡。
  3. 自定義選項卡內容:使用者可以透過自定義選項卡內容(例如圖片、文字、圖示等)來增強頁面的可讀性和可用性。
  4. 載入延遲:如果頁面需要載入大量資料或內容,Tabs元件可以透過延遲載入未啟用的皮膚來提升頁面效能。

🔎1.基本佈局

image

Tabs使用花括號包裹TabContent,每一個TabContent對應一個tabBar

@Entry
@Component
struct NavigationExample {
  private arr: number[] = [1, 2, 3];

  build() {
    Column() {
      Tabs() {
        TabContent() {
          Text('首頁的內容').fontSize(30)
        }
        .tabBar('首頁')

        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
      }
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

🔎2.導航位置

🦋2.1 底部導航

BarPosition.End設定底部導航

@Entry
@Component
struct NavigationExample {
  private arr: number[] = [1, 2, 3];

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.End }) {
        TabContent() {
          Text('首頁的內容').fontSize(30)
        }
        .tabBar('首頁')

        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
      }
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

🦋2.2 頂部導航

BarPosition.Start設定頂部導航

@Entry
@Component
struct NavigationExample {
  private arr: number[] = [1, 2, 3];

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.Start  }) {
        TabContent() {
          Text('首頁的內容').fontSize(30)
        }
        .tabBar('首頁')

        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
      }
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

🦋2.3 側邊導航

實現側邊導航欄需要設定Tabs的屬性vertical為true

  • vertical為false時,tabbar寬度會預設撐滿螢幕的寬度,需要設定barWidth為合適值。

  • vertical為true時,tabbar的高度會預設實際內容高度,需要設定barHeight為合適值。

@Entry
@Component
struct NavigationExample {
  private arr: number[] = [1, 2, 3];

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.Start  }) {
        TabContent() {
          Text('首頁的內容').fontSize(30)
        }
        .tabBar('首頁')

        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
      }.vertical(true)
      .barWidth(100)
      .barHeight(200)
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

🔎3.導航效果

🦋3.1 限制導航欄的滑動切換

在某些需要進行多級分類的頁面上,如同時存在底部導航欄和頂部導航欄時,因為預設情況下導航欄都支援滑動切換,所以當底部導航欄的滑動效果與頂部導航欄出現衝突時,需要限制底部導航欄的滑動,以避免給使用者帶來不好的體驗。

@Entry
@Component
struct NavigationExample {
  private arr: number[] = [1, 2, 3];

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.End }) {
        TabContent(){
          Column(){

            Tabs({ barPosition: BarPosition.Start  }) {
              TabContent() {
                Text('首頁的內容').fontSize(30)
              }
              .tabBar('首頁')

              TabContent() {
                Text('推薦的內容').fontSize(30)
              }
              .tabBar('推薦')

              TabContent() {
                Text('發現的內容').fontSize(30)
              }
              .tabBar('發現')

              TabContent() {
                Text('我的內容').fontSize(30)
              }
              .tabBar("我的")
            }.vertical(true)
            .barWidth(100)
            .barHeight(200)
          }
          .backgroundColor('#ff08a8f1')
          .width('100%')
        }
        .tabBar('首頁')
        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
      }
      .scrollable(false)

    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

🦋3.2 固定導航欄

Tabs的屬性barMode是控制導航欄是否可以滾動,預設值為Fixed

@Entry
@Component
struct NavigationExample {
  private arr: number[] = [1, 2, 3];

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.End }) {
        TabContent(){
          Column(){

            Tabs({ barPosition: BarPosition.Start  }) {
              TabContent() {
                Text('首頁的內容').fontSize(30)
              }
              .tabBar('首頁')

              TabContent() {
                Text('推薦的內容').fontSize(30)
              }
              .tabBar('推薦')

              TabContent() {
                Text('發現的內容').fontSize(30)
              }
              .tabBar('發現')

              TabContent() {
                Text('我的內容').fontSize(30)
              }
              .tabBar("我的")
            }.vertical(true)
            .barWidth(100)
            .barHeight(200)
          }
          .backgroundColor('#ff08a8f1')
          .width('100%')
        }
        .tabBar('首頁')
        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
      }
      .scrollable(false)
      .barMode(BarMode.Fixed)
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

🦋3.3 滾動導航欄

滾動導航欄需要設定Tabs元件的barMode屬性,預設情況下其值為Fixed,表示為固定導航欄,設定為Scrollable即可設定為可滾動導航欄

@Entry
@Component
struct NavigationExample {
  private arr: number[] = [1, 2, 3];

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.End }) {
        TabContent(){
          Column(){

            Tabs({ barPosition: BarPosition.Start  }) {
              TabContent() {
                Text('首頁的內容').fontSize(30)
              }
              .tabBar('首頁')

              TabContent() {
                Text('推薦的內容').fontSize(30)
              }
              .tabBar('推薦')

              TabContent() {
                Text('發現的內容').fontSize(30)
              }
              .tabBar('發現')

              TabContent() {
                Text('我的內容').fontSize(30)
              }
              .tabBar("我的")

            }.vertical(true)
            .barWidth(100)
            .barHeight(200)
          }
          .backgroundColor('#ff08a8f1')
          .width('100%')
        }
        .tabBar('首頁')
        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
        TabContent() {
          Text('推薦的內容').fontSize(30)
        }
        .tabBar('推薦')

        TabContent() {
          Text('發現的內容').fontSize(30)
        }
        .tabBar('發現')

        TabContent() {
          Text('我的內容').fontSize(30)
        }
        .tabBar("我的")
      }
      .scrollable(false)
      .barMode(BarMode.Scrollable)
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

🔎4.自定義導航欄

自定義導航欄是指在應用開發中,開發者使用自己定製的檢視代替系統自帶的導航欄,以實現更加自由、靈活和符合應用風格的導航欄。自定義導航欄可以包括各種 UI 元素,例如按鈕、文字、圖片、標籤等,以滿足不同應用的需求。自定義導航欄可以幫助應用建立獨特的風格和品牌形象,提高使用者體驗和應用的可用性。

@Builder TabBuilder(title: string, targetIndex: number, selectedImg: Resource, normalImg: Resource) {
  Column() {
    Image(this.currentIndex === targetIndex ? selectedImg : normalImg)
      .size({ width: 25, height: 25 })
    Text(title)
      .fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')
  }
  .width('100%')
  .height(50)
  .justifyContent(FlexAlign.Center)
}
TabContent() {
  Column(){
    Text('我的內容')  
  }
  .width('100%')
  .height('100%')
  .backgroundColor('#007DFF')
}
.tabBar(this.TabBuilder('我的', 0, $r('app.media.mine_selected'), $r('app.media.mine_normal')))

image

🔎5.切換至指定頁籤

要想切換特定的標籤頁,需要使用TabsController。TabsController是Tabs元件的控制器,它用於控制Tabs元件進行標籤頁的切換。使用TabsController的changeIndex方法,可以實現跳轉到指定索引值對應的標籤頁內容。

@Entry
@Component
struct NavigationExample {
  private tabsController : TabsController = new TabsController()
  @State currentIndex:number = 0;

  @Builder TabBuilder(title: string, targetIndex: number) {
    Column() {
      Text(title)
        .fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')
    }
    .onClick(() => {
      this.currentIndex = targetIndex;
      this.tabsController.changeIndex(this.currentIndex);
    })
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
        TabContent(){
          Text('首頁')
        }.tabBar(this.TabBuilder('首頁',0)).backgroundColor(Color.Black)

        TabContent(){
          Text('發現')
        }.tabBar(this.TabBuilder('發現',1)).backgroundColor(Color.Blue)

        TabContent(){
          Text('推薦')
        }.tabBar(this.TabBuilder('推薦',2)).backgroundColor(Color.Red)

        TabContent(){
          Text('我的')
        }
        .tabBar(this.TabBuilder('我的',3)).backgroundColor(Color.Pink)
      }
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

🔎6.滑動切換導航欄

在不使用自定義導航欄的情況下,Tabs元件會預設實現tabBar與TabContent的切換聯動。然而,一旦使用了自定義導航欄,就需要使用TabsController來實現點選頁籤與頁面內容的聯動。但使用TabsController無法實現滑動頁面時,頁面內容對應頁籤的聯動。也就是說,當使用者滑動螢幕切換頁面內容時,頁籤欄無法同步切換至對應的頁籤,這可能會影響使用者的體驗。

@Entry
@Component
struct NavigationExample {
  private tabsController : TabsController = new TabsController()
  @State currentIndex:number = 0;

  @Builder TabBuilder(title: string, targetIndex: number) {
    Column() {
      Text(title)
        .fontColor(this.currentIndex === targetIndex ? '#1698CE' : '#6B6B6B')
    }
    .onClick(() => {
      this.currentIndex = targetIndex;
      this.tabsController.changeIndex(this.currentIndex);
    })
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {
        TabContent(){
          Text('首頁')
        }.tabBar(this.TabBuilder('首頁',0)).backgroundColor(Color.Black)

        TabContent(){
          Text('發現')
        }.tabBar(this.TabBuilder('發現',1)).backgroundColor(Color.Blue)

        TabContent(){
          Text('推薦')
        }.tabBar(this.TabBuilder('推薦',2)).backgroundColor(Color.Red)

        TabContent(){
          Text('我的')
        }
        .tabBar(this.TabBuilder('我的',3)).backgroundColor(Color.Pink)
      }.onChange((index) => {
        this.currentIndex = index
      })
    }
    .height('100%')
    .width('100%')
    .backgroundColor('#F1F3F5')
  }
}

image

🚀寫在最後

  • 如果你覺得這篇內容對你還蠻有幫助,我想邀請你幫我三個小忙:
  • 點贊,轉發,有你們的 『點贊和評論』,才是我創造的動力。
  • 關注小編,同時可以期待後續文章ing🚀,不定期分享原創知識。
  • 更多鴻蒙最新技術知識點,請關注作者部落格:https://t.doruo.cn/14DjR1rEY

image

相關文章