iOS自定义TabBar

0 阅读4分钟

DDTabBar 自定义 TabBar

概述

DDTabBar 模块底部导航栏的自定义实现,

  • 支持 普通样式液态玻璃(Liquid Glass)样式 双形态切换。
  • 支持暗黑模式和长辈模式
  • 支持Lottie,gif,png图片资源
  • 支持自定义角标,小红点
  • 根据接口动态更新item数量,顺序

效果

液态玻璃-暗黑

暗黑

液态玻璃-白天

普通模式

长辈版


目录结构

DDTabBar/
├── Manager/                    # 管理与加载
│   ├── DDTabBarManager.swift           # TabBar 单例、数据与配置
│   ├── DDTabBarItemOperationBadgeView.swift  # 运营角标
│   ├── TabBarCacheManager.swift        # 配置缓存
│   ├── TabBarResourceLoader.swift      # 图标/Lottie 资源加载
│   └── TabbarRNRouterInterceptor.swift # RN 路由拦截
├── Model/
│   ├── DDTabBarItem.swift              # (预留) Item 定义
│   └── TabBarModel.swift               # TabBar 与 Item 数据模型
├── Util/
│   ├── DDTaBarEnum.h                   # 枚举:场景、Item 类型、图片类型
│   └── DDTabBarUtil.swift              # 工具:曝光埋点、数据比较等
└── View/
    ├── DDTabBar.swift                  # 主入口:双样式容器与切换逻辑
    ├── DDTabBarItemBadgeView.swift     # 角标视图
    ├── DDTabBarItemContainer.swift     # 单个 Tab 容器(可点击)
    ├── DDTabBarItemContentView.swift   # Tab 内容(图标+文案+角标)
    ├── TabbarWebViewController.swift   # Web Tab 落地页
    └── README.md                       # 本文档

双样式架构

1. 样式类型

样式类名说明
普通样式DDTabBarNormalView全宽 TabBar,毛玻璃 + 背景图/背景色,常规布局
液态玻璃DDTabBarLiquidGlassView圆角胶囊容器,iOS 26 下使用 UIGlassEffect,支持暗黑适配

2. 切换条件

液态玻璃是否展示由 DDTabBar.isLiquidGlassActive() 决定:

  • DDLiquidGlassManager.shared.isLiquidGlassActive == true
  • 非长辈版:!DDBasicInfoManager.shared.isAPVersion

满足时显示 DDTabBarLiquidGlassView,否则显示 DDTabBarNormalView

3. 状态同步

  • 通过通知监听并刷新当前展示的样式:
    • DDLiquidGlassManager.StateDidChangedNotification:液态玻璃开关变化
    • .DDDarkModeShowDarkChanged:暗黑模式变化
    • kChangeToAPVersionNotification:长辈版切换
  • 两种视图的数据与选中索引会同时更新,保证切换样式时状态一致。

主入口实现细节(DDTabBar)

  • ** 默认数据,缓存数据,接口数据 调用update时更新DDTabBarLiquidGlassView 和DDTabBarNormalView,更新时先判断内存中是否有该tab,只更新tab数据不影响飘红角标,没有则创建tab的view;
  • **更新前为每个 Item 设置暗黑图(checkDataDark / uncheckDataDark 按 itemType 取本地图名)。
  • 布局layoutSubviewsnormalView.frame = boundsliquidGlassView.frame = bounds,两套视图始终叠在同一区域,通过 isHidden 切换显示。
  • 长辈版高度sizeThatFitsDDBasicInfoManager.shared.isAPVersion 时高度 +17pt。

普通样式(DDTabBarNormalView)

视图层级与布局

  • 子视图顺序(自底向上):visualEffectView(全 bounds)→ backgroundImageView(全 bounds)→ contentView(全 bounds)。

  • Item 布局:全宽均分布局,itemHeight 默认 48。

  • 首页小火箭:对第一个 item 容器附加首页“小火箭”视图(HomeTabBarItem),用于首页特殊动效/回到顶部能力的承载。

  • 暗黑:不支持暗黑


液态玻璃样式(DDTabBarLiquidGlassView)

1. 视觉与层级

  • 容器:圆角胶囊,宽度 kScreenWidth - 30,水平居中,高度 62pt(containerH
  • 层级(自底向上):
    • shadowView:暗色模糊视图,用于阴影/暗黑增强
    • effectView:使用系统新增的玻璃效果(UIGlassEffect),并开启交互能力(interactive)以获得更自然的玻璃触感与动态反馈)
    • contentView:放置各个tabItem
    • segmentControl:iOS 26UISegmentedControl具有点击拖动有放大镜效果,用于事件响应,UISegmentedControl有valueChanged,但我们还要求再次点击同一个item业务,切换到目标item时,若是拦截的需要把selectedSegmentIndex设置为上一个lastSelectedIndex

虽然给 segmentControl.insertSegment(withTitle: "", at: idx, animated: false)

但仍需要设置,不然会有灰色的背景

DispatchQueue.main.async {
            for subview in self.segmentControl.subviews {
                if subview is UIImageView && subview != self.segmentControl.subviews.last {
                    subview.alpha = 0
                }
            }
        }

3. 暗黑与选中态

  • isCurrentShowDark 控制:
    • 选中槽背景色:暗黑时为 RGBA(0x000000, 0.2),否则为 gray.withAlphaComponent(0.15)
    • 暗黑时显示 shadowView,非暗黑时隐藏
  • Item 使用 isSupportDark = true,会使用模型中的 checkDataDark / uncheckDataDark 等暗黑资源。

DDTabBarItemContentView

ContentView(DDTabBarItemContentView)

  • 子视图iconImageView(DDIconImageView,支持 Lottie/静图/Gif)、titleLabelbusinessBadgeView(运营角标)、badgeView(数字/红点角标)。
  • 两种展示模式itemData.style):
    • style 0(小图):图片和文字的形式。
    • style 1(大图):只有一个大图;titleLabel.isHidden = trueiconImageView.isHidden = false
  • 选中/未选:根据 selectedDDDarkModeManager.shared.isCurrentShowDarkisSupportDark 选择 checkResource/checkDataDarkuncheckResource/uncheckDataDark 及对应文字颜色,调用 iconImageView.setData(data:type:style)iconImageView.play()

数据与展示

1. 数据流概览

  • 配置来源DDTabBarManager.getTabBarConfigData(scene:parmars:aipComplet:) 拉取接口,经 TabBarResourceLoader 下载图标/Lottie 后,由 dealTabBarData 更新 tabBarModel 并调用 tabBar.update(data:items:)
  • 模型
    • TabBarModel:整条 Tab 配置(背景色/图、bottom_list、场景、来源等)
    • TabBarItemModel:单个 Tab(类型、文案、选中/未选资源、链接、角标等)

与系统 UITabBar 的配合

  • DDTabBar 作为自定义视图加在 TabBarController 的 tabBar 上,系统自带的 Tab 按钮需隐藏。代码中通过 UITabBar 的 extension 重写 addGestureRecognizer,对名为 _UIContinuousSelectionGestureRecognizer 的类禁用;

  • 并暴露 recursiveFindTabButtons(in:),递归查找 _UITabBarButton_UITabButton 设为 isHidden = true,以及 _UITabBarPlatterView 隐藏,从而只展示自定义的 DDTabBar 内容。

此处会对私有属性怎混淆处理


小结

能力说明
双样式普通样式(全宽毛玻璃+背景)与液态玻璃样式(圆角胶囊 + iOS26 玻璃效果)
切换由液态玻璃开关 + 是否长辈版决定,通过通知自动刷新
iOS 26液态玻璃使用 UIGlassEffect + 染色层,暗黑下配合阴影与暗色选中槽
数据接口 → TabBarModel/TabBarItemModel → 两套 View 同步更新与选中索引
埋点点击/曝光均带 liquidGlassState 区分 liquid / other