Tabs切换时进行弹窗拦截
=============

#### 问题现象

在Tabs将要切换时，如何弹出弹窗拦截此次切换，并当在弹窗中执行一些指令后，关闭弹窗，并决定完成或取消此次切换。

#### 效果预览

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/e0/v3/uo5Z3dF6QPajAEXNSgKFBQ/zh-cn_image_0000002658969529.png?HW-CC-KV=V1&HW-CC-Date=20260709T133958Z&HW-CC-Expire=86400&HW-CC-Sign=2D73ECA9954000FC65E02B73EAE48468FFF256777E54878AA1E5B67DCDBFE378 "点击放大")

#### 背景知识

*   [Tabs](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs)组件通过页签进行内容视图切换的容器组件，每个页签对应一个内容视图。可以使用[TabsController](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs#tabscontroller)控制Tabs组件进行页签切换。
*   Tab页签点击后触发[onTabBarClick](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs#ontabbarclick10)事件，入参为被点击的index索引。

#### 解决方案

点击Tabs自带的页签会触发onTabBarClick回调，页面也会立即切换，即使在此回调中设置弹窗也无法达到预期效果。

可以自定义标签栏，在标签栏的点击回调中通过使用[changeIndex](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-container-tabs#changeindex)方法控制跳转。具体示例如下：

@Entry
@Component
struct TabsDialogDemo {
  private controller: TabsController \= new TabsController();
  @State currentIndex: number \= 0;
  @State selectIndex: number \= -1;
  lastIndex: number \= 0;
  private customDialogComponentId: number \= 0;
  tabArray: Array<string\> = \['部门', '用户'\];

  @Builder
  customDialogComponent() {
    Column({ space: 12 }) {
      Text('弹窗').fontSize(24);
      Text('是否跳转').margin({ top: 16, bottom: 16 });
      Row() {
        Button('取消', { buttonStyle: ButtonStyleMode.TEXTUAL }).width('40%').onClick(() \=\> {
          _//_ _关闭自定义对话框_
          this.getUIContext().getPromptAction().closeCustomDialog(this.customDialogComponentId);
         _ // 设置当前索引为上一次索引，不进行跳转操作_
          this.currentIndex \= this.lastIndex;
        });
        Divider().vertical(true).height('20');
        Button('跳转', { buttonStyle: ButtonStyleMode.TEXTUAL }).width('40%').onClick(() \=\> {
       _   // 关闭自定义对话框_
          this.getUIContext().getPromptAction().closeCustomDialog(this.customDialogComponentId);
        _  // 设置当前索引和上次索引_
          this.lastIndex \= this.currentIndex \= this.selectIndex;
       _   // 调用控制器改变索引_
          this.controller.changeIndex(this.currentIndex);
        });
      }.width('80%')
      .justifyContent(FlexAlign.SpaceBetween);
    }.padding(24).justifyContent(FlexAlign.SpaceBetween);
  }

  @Builder
  tabBar(tabName: string, tabIndex: number) {
    Row({ space: 20 }) {
      Text(tabName).fontSize(18)
        .textAlign(TextAlign.Center)
        .width('100')
        .fontColor(tabIndex \=== this.currentIndex ? '#0A59F7' : Color.Black);
    }
    .justifyContent(FlexAlign.SpaceBetween)
    .width('100')
    .height(60)
    .onClick(() \=\> {
     _ // 如果当前索引等于标签索引，则不执行任何操作_
      if (this.currentIndex \=== tabIndex) {
        return;
      }
     _ // 设置上一次索引为当前索引_
      this.currentIndex \= this.lastIndex;
      _//_ _设置选择的索引为新标签索引_
      this.selectIndex \= tabIndex;
    _  // 打开自定义对话框_
      this.getUIContext().getPromptAction().openCustomDialog({
        builder: () \=\> {
          this.customDialogComponent();
        },
        width: 328
      }).then((dialogId: number) \=\> {
        this.customDialogComponentId \= dialogId;
      });
    });
  }

  build() {
    Column() {
     _ // 自定义标签栏_
      Row() {
        Scroll() {
          Row() {
            ForEach(this.tabArray, (item: string, index: number) \=\> {
              this.tabBar(item, index);
            });
          }.justifyContent(FlexAlign.Center);
        }
        .align(Alignment.Center)
        .scrollable(ScrollDirection.Horizontal)
        .scrollBar(BarState.Off)
        .width('100%');
      }.alignItems(VerticalAlign.Center)
      .width('100%');

      Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
        TabContent() {
          Text('部门');
        };

        TabContent() {
          Text('用户');
        };
      }
      .vertical(false)
      .barWidth('100%')
      .scrollable(false);
    }
    .height('100%')
    .width('100%');
  }
}