鸿蒙HarmonyOS实战-ArkUI组件(Tabs)

🚀一、Tabs

Tabs组件是一种常见的用户界面(UI)组件,它是一个可以容纳多个选项卡的容器组件。每个选项卡通常包含一个面板和一个标签,用户可以通过点击标签来切换面板。Tabs组件通常用于展示多个相关但又不需要同时展示的数据集合或功能集合,以提高页面的可维护性和可用性。

Tabs组件的主要功能包括:

  1. 切换选项卡:用户可以通过点击标签来切换显示面板。
  2. 激活状态:当前选中的标签会呈现激活状态,以便用户清楚地知道他们当前所在的选项卡。
  3. 自定义选项卡内容:用户可以通过自定义选项卡内容(例如图片、文本、图标等)来增强页面的可读性和可用性。
  4. 加载延迟:如果页面需要加载大量数据或内容,Tabs组件可以通过延迟加载未激活的面板来提升页面性能。

🔎1.基本布局

Tabs使用花括号包裹TabContent,每一个TabContent对应一个tabBar

scss 复制代码
@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')
  }
}

🔎2.导航位置

🦋2.1 底部导航

BarPosition.End设置底部导航

scss 复制代码
@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')
  }
}

🦋2.2 顶部导航

BarPosition.Start设置顶部导航

scss 复制代码
@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')
  }
}

🦋2.3 侧边导航

实现侧边导航栏需要设置Tabs的属性vertical为true

  • vertical为false时,tabbar宽度会默认撑满屏幕的宽度,需要设置barWidth为合适值。
  • vertical为true时,tabbar的高度会默认实际内容高度,需要设置barHeight为合适值。
scss 复制代码
@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')
  }
}

🔎3.导航效果

🦋3.1 限制导航栏的滑动切换

在某些需要进行多级分类的页面上,如同时存在底部导航栏和顶部导航栏时,因为默认情况下导航栏都支持滑动切换,所以当底部导航栏的滑动效果与顶部导航栏出现冲突时,需要限制底部导航栏的滑动,以避免给用户带来不好的体验。

scss 复制代码
@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')
  }
}

🦋3.2 固定导航栏

Tabs的属性barMode是控制导航栏是否可以滚动,默认值为Fixed

scss 复制代码
@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')
  }
}

🦋3.3 滚动导航栏

滚动导航栏需要设置Tabs组件的barMode属性,默认情况下其值为Fixed,表示为固定导航栏,设置为Scrollable即可设置为可滚动导航栏

scss 复制代码
@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')
  }
}

🔎4.自定义导航栏

自定义导航栏是指在应用开发中,开发者使用自己定制的视图代替系统自带的导航栏,以实现更加自由、灵活和符合应用风格的导航栏。自定义导航栏可以包括各种 UI 元素,例如按钮、文本、图片、标签等,以满足不同应用的需求。自定义导航栏可以帮助应用创建独特的风格和品牌形象,提高用户体验和应用的可用性。

scss 复制代码
@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)
}
scss 复制代码
TabContent() {
  Column(){
    Text('我的内容')  
  }
  .width('100%')
  .height('100%')
  .backgroundColor('#007DFF')
}
.tabBar(this.TabBuilder('我的', 0, $r('app.media.mine_selected'), $r('app.media.mine_normal')))

🔎5.切换至指定页签

要想切换特定的标签页,需要使用TabsController。TabsController是Tabs组件的控制器,它用于控制Tabs组件进行标签页的切换。使用TabsController的changeIndex方法,可以实现跳转到指定索引值对应的标签页内容。

scss 复制代码
@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')
  }
}

🔎6.滑动切换导航栏

在不使用自定义导航栏的情况下,Tabs组件会默认实现tabBar与TabContent的切换联动。然而,一旦使用了自定义导航栏,就需要使用TabsController来实现点击页签与页面内容的联动。但使用TabsController无法实现滑动页面时,页面内容对应页签的联动。也就是说,当用户滑动屏幕切换页面内容时,页签栏无法同步切换至对应的页签,这可能会影响用户的体验。

scss 复制代码
@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')
  }
}

🚀写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取最新鸿蒙学习资料,请点击→全套鸿蒙HarmonyOS学习资料
相关推荐
大白要努力!1 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
Estar.Lee1 小时前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
Winston Wood1 小时前
Perfetto学习大全
android·性能优化·perfetto
SameX3 小时前
HarmonyOS Next 安全生态构建与展望
前端·harmonyos
SameX3 小时前
HarmonyOS Next 打造智能家居安全系统实战
harmonyos
Dnelic-4 小时前
【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录
android·junit·单元测试·android studio·自学笔记
Eastsea.Chen6 小时前
MTK Android12 user版本MtkLogger
android·framework
Random_index11 小时前
#Uniapp篇:支持纯血鸿蒙&发布&适配&UIUI
uni-app·harmonyos
长亭外的少年14 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
鸿蒙自习室14 小时前
鸿蒙多线程开发——线程间数据通信对象02
ui·harmonyos·鸿蒙