HarmonyOS Next 系列之底部标签栏TabBar实现(三)

系列文章目录

HarmonyOS Next 系列之省市区弹窗选择器实现(一)
HarmonyOS Next 系列之验证码输入组件实现(二)
HarmonyOS Next 系列之底部标签栏TabBar实现(三)
HarmonyOS Next 系列之HTTP请求封装和Token持久化存储(四)
HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现(五)
HarmonyOS Next 系列之可移动悬浮按钮实现(六)
HarmonyOS Next 系列之沉浸式状态实现的多种方式(七)
HarmonyOS Next系列之Echarts图表组件(折线图、柱状图、饼图等)实现(八)
HarmonyOS Next系列之地图组件(Map Kit)使用(九)
HarmonyOS Next系列之半圆环进度条实现(十)
HarmonyOS Next 系列之列表下拉刷新和触底加载更多数据实现(十一)
HarmonyOS Next系列之实现一个左右露出中间大两边小带缩放动画的轮播图(十二)



前言

HarmonyOS Next(基于API11)实现页面级容器——底部标签栏TabBar

在这里插入图片描述


一、实现原理

Tabs+TabContent+自定义tabbar构建整个页面级TabBar容器,其中子组件TabContent的tabBar属性支持传入自定义构建函数,通过自定义构建函数可以灵活布局整个底部标签样式,最后通过TabsController控制器实现页面切换

在这里插入图片描述

二、代码实现

1.自定义构建函数绘制单个标签样式


//tabBuilder自定义构建函数入参类型
interface BuilderParams {
  index: number //标签索引
  label: string //标签名称
  normalIcon: Resource //未选中状态图标
  selectIcon: Resource //选中状态图标
}

@Entry
@Component
struct TabBar{
  controller: TabsController = new TabsController()//tabs控制器
  @State current: number = 0//当前tab选中项的索引

@Builder //每个tab标签样式布局
  tabBuilder($$: BuilderParams) {
    Column() {
      //图标
      Image(this.current === $$.index ? $$.selectIcon : $$.normalIcon).width(26)
      //文字
      Text($$.label)
        .fontSize('12fp')
        .fontColor(this.current === $$.index ? '#62C9D0' : '#909090')
        .margin({ top: 3 })
    }
    .width('100%')
    .onClick(()=>{
    //点击切换页面
       this.current=$$.index
       this.controller.changeIndex(this.current)//切换到当前页
    })
  }

在这里插入图片描述

说明:通过自定义构建函数tabBuilder绘制了单个标签块内容,垂直容器内添加一个图标和标题,入参包括当前标签索引、标题、激活状态下图标和未激活状态图标。通过入参索引和当前tabbar选中的位置current值判断是否处于选中状态,最后通过TabsController 控制器响应点击事件切换标签页

2.Tabs构建整个TabBar页面级容器

build() {
    Column() {
      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
        TabContent() {
          Text('1')//首页内容
        }.tabBar(this.tabBuilder({
          index: 0,//索引
          label: '首页',//标签
          normalIcon: $r('app.media.tabbar11'),//未选中图标
          selectIcon: $r('app.media.tabbar12')//选中图标
        }))

        TabContent() {
          Text('2')//发现页内容
        }.tabBar(this.tabBuilder({
          index: 1,
          label: '发现',
          normalIcon: $r('app.media.tabbar21'),
          selectIcon: $r('app.media.tabbar22')
        }))

        TabContent() {
          Text('3')//购物车页内容
        }.tabBar(this.tabBuilder({
          index: 2,
          label: '购物车',
          normalIcon: $r('app.media.tabbar31'),
          selectIcon: $r('app.media.tabbar32')
        }))

        TabContent() {
          Text('4')//我的页内容
        }.tabBar(this.tabBuilder({
          index: 3,
          label: '我的',
          normalIcon: $r('app.media.tabbar41'),
          selectIcon: $r('app.media.tabbar42')
        }))

      }
      .width('100%')
      .barMode(BarMode.Fixed)//平均分配barWidth宽度
      .scrollable(true) //滑动页面切换tab
      //与tabcontent分割线样式
      .divider({
        color: '#dedede',
        strokeWidth: 1
      })
      .barBackgroundColor(Color.White)
      .onChange(((index:number)=>{
        this.current=index
      }))
    }.width('100%')
    .backgroundColor('#f2f2f2')
  }

说明:Tabs内嵌4个TabContent子组件分别对应标签页内容,TabContent各自加载自定义构建函数绘制底部标签栏样式。示例中Text(‘1’)//首页内容, Text(‘2’)//发现页内容为标签页面显示内容,实际开发中可单独创建组件文件引入开发,方便维护。


完整代码

TabBar.ets

//tabItem自定义构建函数入参类型
interface BuilderParams {
  index: number //标签索引
  label: string //标签名称
  normalIcon: Resource //未选中状态图标
  selectIcon: Resource //选中状态图标
}

@Entry
@Component
struct TabBar {
  controller: TabsController = new TabsController()//tabs控制器
  @State current: number = 0//当前tab选中项的索引

  @Builder //每个tabItem样式布局
  tabBuilder($$: BuilderParams) {
    Column() {
      //图标
      Image(this.current === $$.index ? $$.selectIcon : $$.normalIcon).width(26)
      //文字
      Text($$.label)
        .fontSize('12fp')
        .fontColor(this.current === $$.index ? '#62C9D0' : '#909090')
        .margin({ top: 3 })
    }
    .width('100%')
    .onClick(()=>{
       this.current=$$.index
       this.controller.changeIndex(this.current)//切换到当前页
    })
  }

  build() {
    Column() {
      Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
        TabContent() {
          Text('1')//首页内容
        }.tabBar(this.tabBuilder({
          index: 0,//索引
          label: '首页',//标签
          normalIcon: $r('app.media.tabbar11'),//未选中图标
          selectIcon: $r('app.media.tabbar12')//选中图标
        }))

        TabContent() {
          Text('2')//发现页内容
        }.tabBar(this.tabBuilder({
          index: 1,
          label: '发现',
          normalIcon: $r('app.media.tabbar21'),
          selectIcon: $r('app.media.tabbar22')
        }))

        TabContent() {
          Text('3')//购物车页内容
        }.tabBar(this.tabBuilder({
          index: 2,
          label: '购物车',
          normalIcon: $r('app.media.tabbar31'),
          selectIcon: $r('app.media.tabbar32')
        }))

        TabContent() {
          Text('4')//我的页内容
        }.tabBar(this.tabBuilder({
          index: 3,
          label: '我的',
          normalIcon: $r('app.media.tabbar41'),
          selectIcon: $r('app.media.tabbar42')
        }))

      }
      .width('100%')
      .barMode(BarMode.Fixed)//平均分配barWidth宽度
      .scrollable(true) //滑动页面切换tab
      //与tabcontent分割线样式
      .divider({
        color: '#dedede',
        strokeWidth: 1
      })
      .barBackgroundColor(Color.White)
      .onChange(((index:number)=>{
        this.current=index
      }))
    }.width('100%')
    .backgroundColor('#f2f2f2')
  }
}

运行效果:
在这里插入图片描述
在这里插入图片描述

好的,针对你的问题,我可以给你一些思路和建议。首先,我们需要明确一下问题的背景和需求: 1. 多页面:指的是我们的项目中有多个页面,而不是单页应用(SPA)。 2. 共用底部导航:指的是我们需要在每个页面中都展示同一个底部导航,这个导航通常被称为 Tabbar。 基于以上需求,我们可以考虑使用 Vue.js 和 Vant UI 组件库来实现多页面共用底部导航。具体实现步骤如下: 1. 创建多个页面:在项目中创建多个页面,每个页面对应一个路由。这些页面可以是纯 HTML 页面,也可以是基于 Vue.js 框架开发的页面。 2. 定义底部导航组件:在 Vant UI 组件库中提供了 Tabbar 组件,我们可以使用这个组件来实现底部导航。在 Vue.js 中定义一个底部导航组件,将 Tabbar 组件作为该组件的一部分。 3. 在路由中引入底部导航组件:在每个页面的路由中引入底部导航组件,并将组件渲染在页面的底部。这样每个页面就都会展示同一个底部导航。 4. 处理底部导航的选中状态:由于底部导航是共用的,所以需要在不同的页面中处理导航的选中状态。我们可以通过路由的钩子函数来实现这一功能。比如在路由的 beforeEach 钩子函数中,根据当前路由的 path 来设置导航的选中状态。 以上就是实现多页面共用底部导航的大致思路和步骤。当然,具体的实现可能还需要根据项目的具体需求进行一些调整和优化。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值