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

Swift iOS:如何设置导航栏背景图片不被拉伸?

解决导航栏背景图拉伸问题的几种方案

你遇到的这个问题很常见,默认设置导航栏背景图时,系统会直接将图片拉伸至导航栏的尺寸,导致比例失调。下面给你几种实用的解决方法,根据你的图片类型和需求选择即可:

方法一:使用可拉伸/平铺图片(适合重复图案或可拉伸的背景)

如果你的背景图是可以重复平铺的图案,或者有固定的可拉伸区域,可以通过resizableImage来设置,让图片要么平铺重复,要么只拉伸指定区域:

if let bgImage = UIImage(named: "BG.jpg") {
    // 选择平铺模式(图片重复显示,不拉伸)
    let tiledImage = bgImage.resizableImage(withCapInsets: UIEdgeInsets.zero, resizingMode: .tile)
    self.navigationController?.navigationBar.setBackgroundImage(tiledImage, for: .default)
    
    // 如果你的图片有不可拉伸的边缘(比如圆角边框),可以设置capInsets指定不拉伸的区域
    // 示例:上下左右各保留20pt不拉伸,中间区域拉伸
    // let stretchableImage = bgImage.resizableImage(withCapInsets: UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20), resizingMode: .stretch)
}

方法二:自定义导航栏背景视图(精确控制显示比例)

这种方法通过添加UIImageView作为导航栏的背景,能灵活设置图片的显示模式(比如保持比例填充、保持比例适应):

guard let navigationBar = self.navigationController?.navigationBar, 
      let bgImage = UIImage(named: "BG.jpg") else { return }

// 先清空默认的背景图和阴影
navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationBar.shadowImage = UIImage()

// 创建图片视图并设置显示模式
let imageView = UIImageView(image: bgImage)
imageView.contentMode = .scaleAspectFill // 保持比例填充,超出导航栏的部分会被裁剪
// 如果你想让图片完整显示(可能留空),可以用.scaleAspectFit
// imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true

// 添加到导航栏并设置约束铺满
navigationBar.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    imageView.topAnchor.constraint(equalTo: navigationBar.topAnchor),
    imageView.leadingAnchor.constraint(equalTo: navigationBar.leadingAnchor),
    imageView.trailingAnchor.constraint(equalTo: navigationBar.trailingAnchor),
    imageView.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor)
])

// 将图片视图放到最底层,避免遮挡导航栏内容
navigationBar.sendSubviewToBack(imageView)

方法三:重新绘制图片适配导航栏尺寸(生成完美匹配的背景图)

如果希望图片严格匹配导航栏尺寸且保持比例,可以通过UIGraphicsImageRenderer重新绘制图片,裁剪或填充到导航栏的大小:

guard let navigationBar = self.navigationController?.navigationBar, 
      let bgImage = UIImage(named: "BG.jpg") else { return }

let barSize = navigationBar.bounds.size
let renderer = UIGraphicsImageRenderer(size: barSize)

let adjustedImage = renderer.image { context in
    let targetRect = CGRect(origin: .zero, size: barSize)
    // 计算保持比例的绘制区域
    let imageAspect = bgImage.size.width / bgImage.size.height
    let barAspect = barSize.width / barSize.height
    
    var drawRect: CGRect
    if imageAspect > barAspect {
        // 图片比导航栏宽,高度铺满,横向居中裁剪
        let drawHeight = barSize.height
        let drawWidth = drawHeight * imageAspect
        drawRect = CGRect(x: (barSize.width - drawWidth)/2, y: 0, width: drawWidth, height: drawHeight)
    } else {
        // 图片比导航栏高,宽度铺满,纵向居中裁剪
        let drawWidth = barSize.width
        let drawHeight = drawWidth / imageAspect
        drawRect = CGRect(x: 0, y: (barSize.height - drawHeight)/2, width: drawWidth, height: drawHeight)
    }
    
    bgImage.draw(in: drawRect)
}

navigationBar.setBackgroundImage(adjustedImage, for: .default)

根据你的实际需求选择对应的方案就好啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:51:52