You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UITabBarController外观自定义方法仅首次调用生效问题

问题原因

方法重复调用失效是三个代码逻辑问题导致的:

  • 每次调用都初始化全新的UITabBarAppearance实例,调用configureWithOpaqueBackground()会把新实例的所有样式重置为系统默认值,直接全量覆盖TabBar原有配置。如果后续调用时只传入部分参数,未传入的样式会直接回退到系统默认,而非保留上一次的设置,看起来就像修改没有生效。
  • 部分iOS 14~16版本存在TabBar样式缓存机制:TabBar完成首次渲染后,仅修改standardAppearance/scrollEdgeAppearance不会立即触发所有TabBarItem的样式重绘,同时旧API属性tintColor的优先级在部分系统版本中高于Appearance配置,会覆盖你设置的选中色。
  • 遗漏了紧凑布局下的compactAppearance、滚动紧凑布局下的compactScrollEdgeAppearance属性赋值,横屏等场景下样式更新不会生效。
修复方案

调整Appearance初始化逻辑(基于当前已有的样式拷贝修改,而非新建空实例),补全缺失的属性赋值和强制布局刷新逻辑即可,修复后的完整代码如下:

/* ###################################################################################################################################### */
// MARK: - UITabBarController Extension -
/* ###################################################################################################################################### */
/**
 快速设置UITabBar颜色样式的扩展
 */
public extension UITabBarController {
    /* ################################################################## */
    /**
     设置TabBar不同状态下的颜色
     所有参数可选,未传入的参数保留上一次设置的值
     - parameters:
        - normal: 未选中、可用状态下的Tab项颜色
        - selected: 选中状态下的Tab项颜色
        - disabled: 不可用状态下的Tab项颜色
        - focused: 聚焦状态下的Tab项颜色
        - background: TabBar背景色
     */
    func setColorsTo(normal inNormalColor: UIColor? = nil,
                     selected inSelectedColor: UIColor? = nil,
                     disabled inDisabledColor: UIColor? = nil,
                     focused inFocusedColor: UIColor? = nil,
                     background inBackgroundColor: UIColor? = nil) {
        // 基于当前已有的Appearance拷贝,保留之前的配置,而非新建空实例
        let appearance = tabBar.standardAppearance.copy() as! UITabBarAppearance
        appearance.configureWithOpaqueBackground()
        // 同步TabBar的半透明属性,匹配不透明背景配置
        tabBar.isTranslucent = false
        
        if let backgroundColor = inBackgroundColor {
            tabBar.backgroundColor = backgroundColor
            tabBar.barTintColor = backgroundColor
            appearance.backgroundColor = backgroundColor
        }

        if let normalColor = inNormalColor {
            appearance.stackedLayoutAppearance.normal.iconColor = normalColor
            appearance.inlineLayoutAppearance.normal.iconColor = normalColor
            appearance.compactInlineLayoutAppearance.normal.iconColor = normalColor
            let normalTextAttributes: [NSAttributedString.Key: Any] = [.foregroundColor: normalColor]
            appearance.stackedLayoutAppearance.normal.titleTextAttributes = normalTextAttributes
            appearance.inlineLayoutAppearance.normal.titleTextAttributes = normalTextAttributes
            appearance.compactInlineLayoutAppearance.normal.titleTextAttributes = normalTextAttributes
        }
        
        if let selectedColor = inSelectedColor {
            // 同步旧API的tintColor,避免低版本系统覆盖选中色
            tabBar.tintColor = selectedColor
            appearance.stackedLayoutAppearance.selected.iconColor = selectedColor
            appearance.inlineLayoutAppearance.selected.iconColor = selectedColor
            appearance.compactInlineLayoutAppearance.selected.iconColor = selectedColor
            let selectedTextAttributes: [NSAttributedString.Key: Any] = [.foregroundColor: selectedColor]
            appearance.stackedLayoutAppearance.selected.titleTextAttributes = selectedTextAttributes
            appearance.inlineLayoutAppearance.selected.titleTextAttributes = selectedTextAttributes
            appearance.compactInlineLayoutAppearance.selected.titleTextAttributes = selectedTextAttributes
        }
        
        if let disabledColor = inDisabledColor {
            appearance.stackedLayoutAppearance.disabled.iconColor = disabledColor
            appearance.compactInlineLayoutAppearance.disabled.iconColor = disabledColor
            appearance.inlineLayoutAppearance.disabled.iconColor = disabledColor
            let disabledTextAttributes: [NSAttributedString.Key: Any] = [.foregroundColor: disabledColor]
            appearance.stackedLayoutAppearance.disabled.titleTextAttributes = disabledTextAttributes
            appearance.inlineLayoutAppearance.disabled.titleTextAttributes = disabledTextAttributes
            appearance.compactInlineLayoutAppearance.disabled.titleTextAttributes = disabledTextAttributes
        }
        
        if let focusedColor = inFocusedColor {
            appearance.stackedLayoutAppearance.focused.iconColor = focusedColor
            appearance.inlineLayoutAppearance.focused.iconColor = focusedColor
            appearance.compactInlineLayoutAppearance.focused.iconColor = focusedColor
            let focusedTextAttributes: [NSAttributedString.Key: Any] = [.foregroundColor: focusedColor]
            appearance.stackedLayoutAppearance.focused.titleTextAttributes = focusedTextAttributes
            appearance.inlineLayoutAppearance.focused.titleTextAttributes = focusedTextAttributes
            appearance.compactInlineLayoutAppearance.focused.titleTextAttributes = focusedTextAttributes
        }

        // 同步所有场景下的Appearance配置
        tabBar.standardAppearance = appearance
        tabBar.compactAppearance = appearance
        if #available(iOS 15.0, *) {
            tabBar.scrollEdgeAppearance = appearance
            tabBar.compactScrollEdgeAppearance = appearance
        }
        
        // 强制触发布局刷新,清除系统缓存的旧样式
        tabBar.setNeedsLayout()
        tabBar.layoutIfNeeded()
    }
}
补充说明
  • 修复后支持任意次数调用,未传入的参数会自动保留上一次的设置,不会回退到系统默认
  • 兼容iOS 13及以上所有系统版本,覆盖普通布局、紧凑布局、滚动边缘场景的样式
  • 如果需要半透明效果,把appearance.configureWithOpaqueBackground()替换为appearance.configureWithDefaultBackground(),同时把tabBar.isTranslucent = false改为tabBar.isTranslucent = true即可

内容的提问来源于stack exchange,提问作者Chris Marshall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 04:51:22