仓颉的 tabbar 参数只支持传入图片或者文字,不能像 ArkTs 那样能传入组件,所以在仓颉语言中官方的 tabbar 局限性非常大。
下面是一段 Tabs 的基本写法:

Tabs(BarPosition.End, this.controller){
 TabContent(){
        Text('页面1')
    }
  TabContent(){
        Text('页面2’)
    }
}

如果你要设置 tabbar 的样式,需要在 TabContent 下添加 tabbar 属性,然后你会发现 tabbar 只有唯二的两个参数:

TabContent(){
        Text('页面1')
    }
   .tabBar(icon: CJResource, text: CJResource)

这样就无法满足我们的需求,所以我们需要自定义。

每一个 tabbar 元素都有一个图片组件和一个文字组件,我给它写出来:

Column {
	 Image(item.selectIcon).width(28).height(28)
         Text(item.title).fontSize(15).fontColor(0xd84642).margin(top: 3)
    }

然后它需要有一个选中状态,难受的是仓颉不支持三元表达式,所以我只能写 if 语句:

Column {
        if(this.currenttabIndex == index){
            Image(item.selectIcon).width(28).height(28)
            Text(item.title).fontSize(15).fontColor(0xd84642).margin(top: 3)
        }else {
             Image(item.icon).width(28).height(28)
            Text(item.title).fontSize(15).fontColor(Color.GRAY).margin(top: 3)
         }
    }

它还需要一个点击事件:

Column {
        if(this.currenttabIndex == index){
            Image(item.selectIcon).width(28).height(28)
            Text(item.title).fontSize(15).fontColor(0xd84642).margin(top: 3)
        }else {
             Image(item.icon).width(28).height(28)
            Text(item.title).fontSize(15).fontColor(Color.GRAY).margin(top: 3)
         }
    }
.onClick({evet => this.currenttabIndex = index;this.controller.changeIndex(Int32(this.currenttabIndex))})

这样一个元素就写好了,接下来我只要循环添加几个元素,一个完整的 tabbar 就写好了,这里大家也要注意一下仓颉中 foreach 的写法:

Row {
        ForEach(this.tabList, itemGeneratorFunc: {item: TabItem, index: Int64 =>
                    Column {
                        if(this.currenttabIndex == index){
                            Image(item.selectIcon).width(28).height(28)
                            Text(item.title).fontSize(15).fontColor(0xd84642).margin(top: 3)
                        }else {
                             Image(item.icon).width(28).height(28)
                            Text(item.title).fontSize(15).fontColor(Color.GRAY).margin(top: 3)
                         }
                    }
                .onClick({evet => this.currenttabIndex = index;this.controller.changeIndex(Int32(this.currenttabIndex))})
    })
}
.width(100.percent)
.height(60)
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.SpaceAround)

最后我们还是需要官方的 Tabs 容器来添加页面,你只要不设置 tabbar 属性底部导航栏区域就是空白的,正好把我们自定义的 tabbar 放上,下面是完整的示例代码:

let tabList: Array<TabItem> = [
    TabItem(@r(app.media.shop_tab_00), @r(app.media.shop_tab_01), '首页'),
     TabItem(@r(app.media.shop_tab_10), @r(app.media.shop_tab_11), '购物车'),
     TabItem(@r(app.media.shop_tab_20), @r(app.media.shop_tab_21), '我的')
    ]
@State
var currenttabIndex:Int64 = 0

Stack(Alignment.Bottom) {
    Tabs(BarPosition.End, this.controller){
     TabContent(){
        home()
        }
        TabContent(){
            shopcar()
        }
        TabContent(){
            mine()
        }
    }
    .barHeight(60)
    .scrollable(false)
    .animationDuration(0)
    
     Row {
        ForEach(this.tabList, itemGeneratorFunc: {item: TabItem, index: Int64 =>
                    Column {
                        if(this.currenttabIndex == index){
                            Image(item.selectIcon).width(28).height(28)
                            Text(item.title).fontSize(15).fontColor(0xd84642).margin(top: 3)
                        }else {
                             Image(item.icon).width(28).height(28)
                            Text(item.title).fontSize(15).fontColor(Color.GRAY).margin(top: 3)
                         }
                    }
                .onClick({evet => this.currenttabIndex = index;this.controller.changeIndex(Int32(this.currenttabIndex))})
    })
}
.width(100.percent)
.height(60)
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.SpaceAround)
}
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐