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

iPhone 12 mini 导航栏渐变背景图着色异常问题排查求助

异常触发原因

  • 导航栏尺寸计算时机错误:在viewDidLoad、viewWillAppear等生命周期节点调用时,导航栏还未完成自动布局,获取到的navigationBar.bounds是初始值,和最终渲染的真实尺寸不符。iPhone 12 mini的逻辑分辨率、状态栏高度参数和其余刘海屏机型存在差异,尺寸不匹配的问题在该机型上被触发。
  • 状态栏高度获取方式不稳定:直接取UIApplication.shared.windows[0]的状态栏高度,多场景(Scene)下第一个window不一定是当前页面所属的window,容易拿到错误的高度值。
  • 渐变图片生成未适配Retina屏:使用UIGraphicsBeginImageContext生成的是1倍分辨率图片,在2倍、3倍屏上会出现拉伸、尺寸错位问题,iPhone 12 mini的3倍屏缩放比例进一步放大了该问题。

修复方案

  1. 调整调用时机:将方法调用放到viewDidLayoutSubviews中,确保导航栏布局完成后再计算尺寸;也可以监听导航栏的bounds属性变化,动态更新背景图。
  2. 修正状态栏高度获取逻辑:从当前视图所属的window中获取状态栏高度,避免取到错误window的参数。
  3. 适配Retina屏生成图片:改用UIGraphicsBeginImageContextWithOptions生成对应分辨率的渐变图片。
  4. 适配新的导航栏API:优先使用iOS 13+推出的UINavigationBarAppearance配置背景,兼容性更强。

修复后的参考代码:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    setNavGradiant()
}

func setNavGradiant(){
    guard let navigationController = self.navigationController,
          let window = view.window,
          let statusBarHeight = window.windowScene?.statusBarManager?.statusBarFrame.height else {
        print("❇️♊️>>> \(#file) \(#line): guard let failed <<<")
        return
    }
    let gradientLayer = CAGradientLayer()
    var updatedFrame = navigationController.navigationBar.bounds
    updatedFrame.size.height += statusBarHeight

    gradientLayer.frame = updatedFrame
    gradientLayer.colors = [ #colorLiteral(red: 0.4392156899, green: 0.01176470611, blue: 0.1921568662, alpha: 1).cgColor,  #colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1).cgColor]
    gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.0)
    gradientLayer.endPoint = CGPoint(x: 0.5, y: 1.0)
    
    // 适配Retina屏生成图片
    UIGraphicsBeginImageContextWithOptions(gradientLayer.bounds.size, false, UIScreen.main.scale)
    guard let context = UIGraphicsGetCurrentContext() else {
        UIGraphicsEndImageContext()
        return
    }
    gradientLayer.render(in: context)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    // 适配新API,兼容性更好
    if #available(iOS 13.0, *) {
        let appearance = UINavigationBarAppearance()
        appearance.backgroundImage = image
        appearance.titleTextAttributes = [.foregroundColor: #colorLiteral(red: 0.9579688907, green: 0.9579688907, blue: 0.9579688907, alpha: 1)]
        navigationController.navigationBar.standardAppearance = appearance
        navigationController.navigationBar.scrollEdgeAppearance = appearance
    } else {
        navigationController.navigationBar.setBackgroundImage(image, for: .default)
        navigationController.navigationBar.titleTextAttributes = [.foregroundColor: #colorLiteral(red: 0.9579688907, green: 0.9579688907, blue: 0.9579688907, alpha: 1)]
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.21 16:36:08