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

iOS13.0+版本导航栏添加渐变后UIBarButtonItem隐藏问题如何解决

问题原因
  • CAGradientLayer初始化逻辑错误:原代码中let gradient = CAGradientLayer(layer: colors)是错误用法,该初始化方法作用是复制已有Layer的属性,传入UIColor数组会导致渐变层颜色配置完全失效,生成的背景图不符合预期,极易出现和按钮文字撞色的情况,导致文字视觉上被“隐藏”。
  • 未配置UIBarButtonItem的文字样式:仅设置了导航栏标题的文字属性,没有配置UIBarButtonItem的普通/高亮状态文字颜色,iOS13+下UIBarButtonItem默认文字颜色会跟随系统样式适配,和你使用的橙红渐变背景色重合时,就会出现全屏状态下看不见、侧滑半透明状态下可见的现象。
  • 渐变图片生成时机错误:配置appearance时直接取当前navigationBar的bounds生成图片,此时导航栏还未完成布局,bounds尺寸错误,生成的背景图片拉伸异常也可能遮挡按钮。
  • 全局样式优先级问题:页面内直接设置全局UINavigationBar.appearance(),如果当前导航控制器或页面有单独的导航栏配置,会覆盖全局样式,导致按钮样式异常。
修复方案

1. 修复渐变图片生成逻辑

修正CAGradientLayer初始化错误,改为传入size参数避免布局未完成导致的尺寸问题:

extension UIImage {
static func getGradientImage(withColors colors: [UIColor], size: CGSize) -> UIImage {
    let gradient = CAGradientLayer()
    // 需把UIColor转换为CGColor
    gradient.colors = colors.map{ $0.cgColor }
    gradient.frame = CGRect(origin: .zero, size: size)
    gradient.locations = [0.0, 1.0]
    gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
    gradient.endPoint = CGPoint(x: 1.0, y: 0.5)
    return UIImage.image(from: gradient) ?? UIImage()
}

 static func image(from layer: CALayer) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(layer.bounds.size,
                                           layer.isOpaque, UIScreen.main.scale)
    defer { UIGraphicsEndImageContext() }
    guard let context = UIGraphicsGetCurrentContext() else {
        return nil
    }
    layer.render(in: context)
    return UIGraphicsGetImageFromCurrentImageContext()
 }
}

2. 补充UIBarButtonItem样式配置

给UINavigationBarAppearance增加按钮样式配置,直接给当前导航栏设置样式替代全局配置,同时显式指定tintColor:

if #available(iOS 13.0, *) {
        let appearance = UINavigationBarAppearance()
        appearance.configureWithOpaqueBackground()
        appearance.backgroundColor = .clear
        appearance.titleTextAttributes = [.foregroundColor: UIColor.white]
        // 新增:配置UIBarButtonItem各状态文字属性
        appearance.buttonAppearance.normal.titleTextAttributes = [.foregroundColor: UIColor.white]
        appearance.buttonAppearance.highlighted.titleTextAttributes = [.foregroundColor: UIColor.white.withAlphaComponent(0.7)]
        // 直接传入导航栏标准尺寸生成背景图
        let navBarWidth = UIScreen.main.bounds.width
        let navBarHeight: CGFloat = UINavigationController().navigationBar.bounds.height
        appearance.backgroundImage = UIImage.getGradientImage(withColors: [#colorLiteral(red: 0.9258083701, green: 0.4127946496, blue: 0, alpha: 1),#colorLiteral(red: 0.7787303329, green: 0.01916297711, blue: 0.1483061314, alpha: 1)], size: CGSize(width: navBarWidth, height: navBarHeight))
        // 直接给当前导航栏设置样式,优先级更高
        navigationController?.navigationBar.standardAppearance = appearance
        navigationController?.navigationBar.scrollEdgeAppearance = appearance
        navigationController?.navigationBar.compactAppearance = appearance
        // 显式指定导航栏tintColor,确保按钮图标/文字颜色正确
        navigationController?.navigationBar.tintColor = .white
    } else {
        // iOS13以下版本也补充tintColor配置
        navigationController?.navigationBar.tintColor = .white
    }

3. 可选:自定义UIBarButtonItem避免系统样式影响

如果修改样式后仍有问题,直接用自定义View创建UIBarButtonItem,完全脱离系统按钮样式限制:

let titleLabel = UILabel()
titleLabel.text = "Top Title"
titleLabel.textColor = .white
titleLabel.font = UIFont.systemFont(ofSize: 16, weight: .medium)
let topTitle = UIBarButtonItem(customView: titleLabel)
self.navigationItem.leftBarButtonItem = topTitle

内容的提问来源于stack exchange,提问作者Saeed Rahmatolahi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 02:54:02