鸿蒙开发自定义TabBar,实现tabBar 上中间按钮凸起效果
第一步、定义数据模型
export default class TabItemData{defaultIcon: ResourceselectedIcon: Resourcetitle: stringisMiddle: booleanconstructor(defaultIcon:Resource, selectedIcon:Resource, title:string, isMiddle: boolean) {this.defaultIcon = defaultIconthis.selectedIcon = selectedIconthis.title = titlethis.isMiddle = isMiddle}
}
第二步、定义一个ViewModel, 设置数据源
export class MainViewModel {getTabBarImage(): Array<TabItemData>{let tabItems: TabItemData[] = [new TabItemData($r('app.media.home_normal'), $r('app.media.home_selected'), "首页", false),new TabItemData($r('app.media.discover_normal'), $r('app.media.discover_selected'), "", true),new TabItemData($r('app.media.mine_normal'), $r('app.media.mine_selected'), "我", false),]return tabItems}}export default new MainViewModel();
第三步、自定义组件,定义一个TabItem,用了两个Column 嵌套,代表两个视图容器,由于鸿蒙没有类似Flutter 中Container 这样的组件,所以选择用Column 代替
@Component
export struct TabBarItem{@Prop isSelected: booleanitemData: TabItemDatabuild(){Column(){Column(){Image(this.isSelected? this.itemData.selectedIcon: this.itemData.defaultIcon).width(this.itemData.isMiddle? '45vp': '25vp').height(this.itemData.isMiddle? '45vp': '25vp').interpolation(ImageInterpolation.High)if (!this.itemData.isMiddle){Text(this.itemData.title).margin({ top: $r('app.float.mainPage_baseTab_top') }).fontSize($r('app.float.main_tab_fontSize')).fontColor(this.isSelected? '#1698CE' : '#6B6B6B')}}.justifyContent(FlexAlign.Center).backgroundColor(this.itemData.isMiddle?Color.White: Color.Transparent).padding(this.itemData.isMiddle?{top:2,left:2, right:2, bottom: 2}: 0).borderRadius('23.5vp')}.justifyContent(FlexAlign.Center).height($r('app.float.mainPage_barHeight')).width(Constants.FULL_PARENT)}
}
第三步、自定义TabBar 组件
@Component
export struct LMTabBar{@Prop tabIdx:numbertabItemClick:(index)=>voidbuild(){Flex(){ForEach(mainViewModel.getTabBarImage(),(item,index: number)=>{TabBarItem({itemData: item, isSelected: this.tabIdx === index }).offset({y: item.isMiddle? '-25': '0'}).onClick(()=>{this.tabIdx = indexthis.tabItemClick(index)})})}}
}
第四步、用自定义的TabBar覆盖原来Tabs
@Preview
@Entry
@Component
struct MainPage{@State currentIndex: number = 0private tabsController: TabsController = new TabsController()build(){Stack(){Tabs({barPosition: BarPosition.End, controller: this.tabsController }){TabContent(){Home()}.padding({ left: $r('app.float.mainPage_padding'), right: $r('app.float.mainPage_padding') }).backgroundColor($r('app.color.mainPage_backgroundColor'))TabContent(){Text("发现")}TabContent(){Mine()}.padding({ left: $r('app.float.mainPage_padding'), right: $r('app.float.mainPage_padding') }).backgroundColor($r('app.color.mainPage_backgroundColor'))}.barHeight(0).onChange((index: number)=>{this.currentIndex = index})LMTabBar({tabIdx: this.currentIndex,tabItemClick: (index)=>{this.tabsController.changeIndex(index)} }).backgroundColor(Color.White)}.align(Alignment.Bottom)}
}