如何设置TabBar布局
============

#### 问题现象

TabBar的布局效果可以根据不同的设计需求来实现多种样式。以下是一些常见的TabBar布局效果：

*   场景一：如何实现不同方向的TabBar布局效果（如侧边垂直布局、底部水平布局等）？
*   场景二：如何实现页签的居中或左右对齐的布局效果？
*   场景三：如何实现TabBar左右分布的布局效果？
*   场景四：如何实现每个页签宽度均不相同的布局效果？
*   场景五：如何实现页签布局根据数量不同，进行动态调整的效果？

#### 背景知识

*   [Tabs组件](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs)：通过页签进行内容视图切换的容器组件，每个页签对应一个内容视图。
*   [tabBar](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabcontent#tabbar)：设置TabBar上显示内容。

#### 解决方案

本文将基于上述场景，逐一阐述其具体实现方式。

| 
问题场景

 | 

问题描述

 | 

解决方案

 |
| :-- | :-- | :-- |
| 

场景一

 | 

实现不同方向的TabBar布局效果。

 | 

通过barPosition属性和vertical属性，实现TabBar不同方向的布局。

 |
| 

场景二

 | 

实现页签的居中或左右对齐的布局效果。

 | 

通过barMode可以设置TabBar布局模式，再加上TabsOptions中的barModifier可以设置tabBar的align属性实现页签对齐布局效果。

 |
| 

场景三

 | 

实现TabBar左右分布的布局效果。

 | 

利用Stack组件自定义TabBar，再使用position属性自定义每一个页签的位置。则可实现页签不均匀分布的效果。

 |
| 

场景四

 | 

实现每个页签宽度均不相同的布局效果。

 | 

通过将barMode设置为BarMode.Scrollable可滚动模式，tabBar的宽度即可以根据实际宽度显示。

 |
| 

场景五

 | 

实现页签布局根据数量不同，进行动态调整的效果。

 | 

通过barGridAlign属性可以实现以栅格化方式设置TabBar的可见区域。将barGridAlign属性与页签个数相结合，即可达到动态调整页签布局的效果。

 |

*   **场景一：实现不同方向的TabBar布局效果。**
    
    可通过[barPosition属性](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs#barposition9)设置页签的位置，其取值为BarPosition.Start或BarPosition.End。默认值为BarPosition.Start，表示页签位于页面顶部；设置为End时，页签则显示在页面底部。
    
    此外，[vertical属性](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs#vertical)用于控制页签的布局方向，默认值为false，表示横向布局（页签位于顶部或底部）；当设为true时，页签变为纵向布局，显示在屏幕左侧或右侧。
    
    综上所述，可以得出下表结论：
    
    | 
    barPosition取值
    
     | 
    
    vertical取值
    
     | 
    
    TabBar位置
    
     |
    | :-- | :-- | :-- |
    | 
    
    BarPosition.Start（默认值）
    
     | 
    
    true
    
     | 
    
    屏幕左侧
    
     |
    | 
    
    BarPosition.Start（默认值）
    
     | 
    
    false（默认值）
    
     | 
    
    屏幕顶部
    
     |
    | 
    
    BarPosition.End
    
     | 
    
    true
    
     | 
    
    屏幕右侧
    
     |
    | 
    
    BarPosition.End
    
     | 
    
    false（默认值）
    
     | 
    
    屏幕底部
    
     |
    
    用TabBar位于屏幕左侧举例，实现代码如下：
    
    @Entry
    @Component
    struct TabBarLayoutInDifferentDirections {
      build() {
        Column() {
          Tabs({
            barPosition: BarPosition.Start
          }) {
            TabContent() {
              Column() {
                Text('首页');
              }.width('100%').height('100%')
              .justifyContent(FlexAlign.Center);
            }.tabBar('首页');
    
            TabContent() {
              Column() {
                Text('商城');
              }.width('100%').height('100%')
              .justifyContent(FlexAlign.Center);
            }.tabBar('商城');
    
            TabContent() {
              Column() {
                Text('我的');
              }.width('100%').height('100%')
              .justifyContent(FlexAlign.Center);
            }.tabBar('我的');
          }.vertical(true)
          .expandSafeArea(\[SafeAreaType.SYSTEM\], \[SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM\]);
        };
      }
    }
    
    实现效果如下：
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/c6/v3/ZYul09dkSXi6sKdzJpCGkA/zh-cn_image_0000002628567120.png?HW-CC-KV=V1&HW-CC-Date=20260709T133930Z&HW-CC-Expire=86400&HW-CC-Sign=B78223BE8CBA25DDE33ADB6E9A9BF077757E7284CA3654B3F2A8E4F454357A65 "点击放大")
    
    *   **场景二：实现页签的居中或左右对齐的布局效果。**
        
        通过[barMode](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs#barmode)可以设置TabBar布局模式，再加上[TabsOptions](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs#tabsoptions15)中的barModifier可以设置tabBar的align属性实现页签对齐布局效果。
        
        详情可参考示例：[页签对齐布局](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs#示例16页签对齐布局)。
        
    *   **场景三：实现TabBar左右分布的布局效果。**
        
        在某些应用场景中，开发者可能需要一个自定义的TabBar布局，其中左边的两个页签居左对齐，右边的两个页签居右对齐，而中间部分则可以放置一个图标或按钮。这种布局方式不仅能够有效利用屏幕空间，还能提供更灵活的导航和功能入口，提升用户体验。
        
        利用Stack组件自定义TabBar，再使用position属性自定义每一个页签的位置。则可实现页签不均匀分布的效果。
        
        实现代码如下：
        
        @Entry
        @Component
        export struct TabBarAlignLeftAndRight {
          currentIndex: number = 0;
          @State selectedIndex: number = 0;
          fontColor: string = '#000';
          selectedFontColor: string = '#0A59F7';
          tabName: Array<string> = \['首页', '商城', '更多', '我的'\];
          private controller: TabsController = new TabsController();
        
          @Builder
          tabBuilder(index: number, name: string) {
            Column() {
              Text(name)
                .fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
                .fontSize(16)
                .fontWeight(this.selectedIndex === index ? 500 : 400)
                .lineHeight(22)
                .margin({ top: 17, bottom: 7 });
            }
            .onClick(() => {
              this.controller.changeIndex(index);
              this.selectedIndex = index;
            })
            .padding(10)
          _  // 设置TabItem的相对位置_
            .position(
              index === 1 ? { left: 80 } :
                index === 2 ? { right: 90 } :
                  index === 3 ? { right: 0 } : {});
          }
        
          build() {
            Stack({ alignContent: Alignment.BottomStart }) {
              Tabs({
                barPosition: BarPosition.End,
                index: this.currentIndex,
                controller: this.controller
              }) {
                TabContent() {
                  Column() {
                    Text('首页');
                  }.width('100%').height('100%')
                  .justifyContent(FlexAlign.Center);
                };
        
                TabContent() {
                  Column() {
                    Text('商城');
                  }.width('100%').height('100%')
                  .justifyContent(FlexAlign.Center);
                };
        
                TabContent() {
                  Column() {
                    Text('更多');
                  }.width('100%').height('100%')
                  .justifyContent(FlexAlign.Center);
                };
        
                TabContent() {
                  Column() {
                    Text('我的');
                  }.width('100%').height('100%')
                  .justifyContent(FlexAlign.Center);
                };
              }
              .barHeight(0)
              .onAnimationStart((index: number, targetIndex: number) => {
                if (index === targetIndex) {
                  return;
                }
                this.selectedIndex = targetIndex;
              });
        
              Stack() {
              _  // 用Row组件实现TabBar效果_
                Row() {
                  ForEach(this.tabName, (item: string, index: number) => {
                    this.tabBuilder(index, item);
                  });
                }
                .justifyContent(FlexAlign.SpaceBetween)
                .alignItems(VerticalAlign.Bottom)
                .width('100%')
                .backgroundColor(Color.White);
        
              _  // 开发者按需设计中间宫格展示内容，该示例展示图标_
                Image($r('app.media.startIcon')) _// 资源地址请自行替换_
                  .width(25)
                  .height(25)
                  .align(Alignment.Bottom);
              };
            };
          }
        }
        
        实现效果如下：
        
        ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/ea/v3/n5G6E465ThyZOBHdTcRF8w/zh-cn_image_0000002658926419.png?HW-CC-KV=V1&HW-CC-Date=20260709T133930Z&HW-CC-Expire=86400&HW-CC-Sign=10C2358F32E1A296854E0AA1F4962FBCA1D90872613716C90316C3BD224513FB "点击放大")
        
    *   **场景四：实现每个页签宽度均不相同的布局效果。**
        
        通过将[barMode](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs#barmode10-1)设置为BarMode.Scrollable可滚动模式，tabBar的宽度即可以根据实际宽度显示。
        
        实现代码如下：
        
        @Entry
        @Component
        struct TabBarLayoutUnevenly {
          build() {
            Column() {
              Tabs() {
                TabContent() {
                  Column() {
                    Text('首页');
                  }.width('100%').height('100%')
                  .justifyContent(FlexAlign.Center);
                }.tabBar('首页');
        
                TabContent() {
                  Column() {
                    Text('一多适配');
                  }.width('100%').height('100%')
                  .justifyContent(FlexAlign.Center);
                }.tabBar('一多适配');
        
                TabContent() {
                  Column() {
                    Text('HarmonyOS应用');
                  }.width('100%').height('100%')
                  .justifyContent(FlexAlign.Center);
                }.tabBar('HarmonyOS应用');
        
                TabContent() {
                  Column() {
                    Text('实况窗');
                  }.width('100%').height('100%')
                  .justifyContent(FlexAlign.Center);
                }.tabBar('实况窗');
              }.barMode(BarMode.Scrollable);
            };
          }
        }
        
        实现效果如下：
        
        ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/dd/v3/pmohc6u-RH25GuWRLAde3w/zh-cn_image_0000002628407220.png?HW-CC-KV=V1&HW-CC-Date=20260709T133930Z&HW-CC-Expire=86400&HW-CC-Sign=5CC623EE7A32CBDEBB6CF840D4CCB2866DF1B7CC6C025DA540C208C87EA7CD0D "点击放大")
        
        更多实现方式和详情可参考示例：[如何给tabBar页签设置不同宽度](https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs/faqs-arkui-580)。
        
    *   **场景五：实现页签布局根据数量不同，进行动态调整的效果。**
        
        通过[barGridAlign属性](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs#bargridalign10)可以实现以栅格化方式设置TabBar的可见区域。将barGridAlign属性与页签个数相结合，即可达到动态调整页签布局的效果。
        
        详情可参考示例：[Tabs如何根据TabBar数量更改页签栏排布](https://developer.huawei.com/consumer/cn/doc/harmonyos-faqs/faqs-arkui-1536)和[设置TabBar栅格化可见区域](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs#示例7设置tabbar栅格化可见区域)。
        

#### 常见FAQ

Q：为什么当barHeight与SubTabBarStyle.of同时设置的时候，文字会出现被部分覆盖的错误样式？

A：子页签的内边距默认值：{left:8.0vp,right:8.0vp,top:17.0vp,bottom:18.0vp}。SubTabBarStyle存在默认的内边距，使用时可以主动设置下：tabBar(SubTabBarStyle.of('文本').padding(0))。