鸿蒙Next Tabs的TabBar中间凸起的另一种实现方案

227 阅读1分钟

前一篇 鸿蒙Next Tabs的TabBar中间凸起的一种实现方案中已经实现类似效果,有个问题是不能给tabBar整体加背景图, 所以更改了一种实现方式。

实现思路:使用自定义将tabs的tabBar高度设为0,自定义实现导航栏,通过@Link做双向绑定,更新选中项, 如果需要底部凸起部分高度显示内容,可以通过给tabs的margin/bottom 设置负值实现内容区域延伸

最终效果如下:

实现方式:

@Component
export struct TabsComponent {
  @State selectedIndex: number = 0;
  private controller: TabsController = new TabsController();
  private listData: Array<string> = []

  aboutToAppear(): void {
    for (let index = 0; index < 100; index++) {
      this.listData.push("item:" + index)
    }
  }

  build() {
    Column() {
      Tabs({ index: this.selectedIndex, barPosition: BarPosition.End, controller: this.controller }) {
        TabContent() {
          List() {
            ForEach(this.listData, (item: string, index) => {
              ListItem() {
                Text(item).padding(10).width('100%')
              }
            })
          }.width('100%').height('100%')
          .divider({ strokeWidth: 1, color: Color.Red })
        }.tabBar()

        TabContent() {
          Text("项目")
            .fontSize(20)
            .padding(20)
        }

        TabContent() {
          Text("广场")
            .fontSize(20)
            .padding(20)
        }

        TabContent() {
          Text("问答")
            .fontSize(20)
            .padding(20)
        }

        TabContent() {
          Text("我的")
            .fontSize(20)
            .padding(20)
        }
      }
      .vertical(false)
      .layoutWeight(1)
      .backgroundColor(Color.Pink)
      .barHeight(0)
      .margin({ bottom: -20 })
      .onChange((index: number) => {
        this.selectedIndex = index;
      })

      // 自定义TabBar组件
      TabBarComponent({ selectedIndex: $selectedIndex })
    }.width("100%")
    .height("100%")
  }
}

@Component
struct TabBarComponent {
  @Link selectedIndex: number;
  tabBarList: Array<string> = ['首页', '项目', '广场', '问答', '我的']

  build() {
    Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.End }) {
      ForEach(this.tabBarList, (item: string, tabIndex: number) => {
        this.TabItem(tabIndex, item)
      })
    }
    .width('100%')
  }

  @Builder
  TabItem(tabBarIndex: number, name: string) {
    Column({ space: 5 }) {
      if (tabBarIndex == 2) {
        Image($r('app.media.icon_shop_car'))
          .size({ width: 60, height: 60 })
          .clip(true)
          .borderWidth(5)
          .borderRadius('100%')
          .borderColor(Color.White)
          .offset({ y: -10 })
          .markAnchor({ y: -10 })
      } else {
        Image($r('app.media.startIcon'))
          .size({ width: 30, height: 30 })
      }
      Text(name).fontSize(14).fontColor((tabBarIndex == this.selectedIndex) ? Color.Red : Color.Black)
    }
    .onClick(() => {
      this.selectedIndex = tabBarIndex
    })
    .width("100%")
  }
}