鸿蒙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学习资料
相关推荐
姑苏风3 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
数据猎手小k6 小时前
AndroidLab:一个系统化的Android代理框架,包含操作环境和可复现的基准测试,支持大型语言模型和多模态模型。
android·人工智能·机器学习·语言模型
你的小107 小时前
JavaWeb项目-----博客系统
android
风和先行8 小时前
adb 命令查看设备存储占用情况
android·adb
AaVictory.8 小时前
Android 开发 Java中 list实现 按照时间格式 yyyy-MM-dd HH:mm 顺序
android·java·list
dawn9 小时前
鸿蒙ArkTS中的获取网络数据
华为·harmonyos
桃花键神9 小时前
鸿蒙5.0时代:原生鸿蒙应用市场引领开发者服务新篇章
华为·harmonyos
鸿蒙自习室9 小时前
鸿蒙多线程开发——并发模型对比(Actor与内存共享)
华为·harmonyos
似霰9 小时前
安卓智能指针sp、wp、RefBase浅析
android·c++·binder
大风起兮云飞扬丶9 小时前
Android——网络请求
android