具有类似 scaleAspectFill 行为的 UINavigationBar 背景图像

dr_*_*rto 3 uinavigationbar uiimage ios swift

tl;博士

我正在尝试为UINavigationBar. 有没有办法配置导航栏,使其使用scaleAspectFill类似行为(作为UIImageViewwith contentModeset to scaleAspectFill)?


目标

我有一张图像大致适合横向 iPhone 的导航栏尺寸(64pt 高度,大约 800pt 宽度;不过,确切的尺寸在这里无关紧要),我用navigationBar.setBackgroundImage(img, for: .default). 图像是一张模糊的照片,所以不需要像素完美。顺便说一句 - 我正在使用UINavigationBar.appearance一次为所有导航栏设置背景。

  1. 我想要它做什么:在纵向时显示图像的中心部分,在横向时显示完整图像而不进行裁剪。如果高度不完全匹配(正如在 iPhone X 上预期的那样),它应该放大一点以填充额外的高度。

  2. 作为后备解决方案,如果较小宽度的图像显示居中并通过拉伸第一个和最后一个像素列来填充额外的水平空间,我也会接受。

到目前为止我尝试过的

  • 目标 1:在渲染图像时设置contentModeof UINavigationBar-- 似乎被忽略
  • 目标 2:使用较小的图像并使其可拉伸stretchableImage(withLeftCapWidth:topCapHeight:)- 填充导航栏但图像被推到右下角(显然是因为此方法仅将左侧和顶部视为可拉伸的边距)
  • 目标 2:使用较小的图像并resizableImage(withCapInsets:resizingMode:)使用resizingModeset to使其可调整大小stretch- 在横向中它只是将图像拉伸到全宽,而忽略了大写插图(可能这种方法并没有按照我的想法行事)。

dr_*_*rto 5

通过将图像视图添加到 的视图来解决UINavigationController,如here所述。图像视图附加到导航控制器视图的顶部、左侧和右侧以及导航栏的底部。

对比文章中的例子,我没有使用自定义导航栏;相反,我在现有导航栏后面插入图像视图。请注意,导航栏必须是透明的才能完成这项工作。此外,必须剪切图像视图,否则它会奇怪地超出导航栏的底部。

也许这对其他人有帮助,所以这里有一些代码(这应该只应用于导航控制器一次,所以也许你最好将此代码放在子类中而不是扩展中):

extension UINavigationController {
  func setBackgroundImage(_ image: UIImage) {
    navigationBar.isTranslucent = true
    navigationBar.barStyle = .blackTranslucent

    let logoImageView = UIImageView(image: image)
    logoImageView.contentMode = .scaleAspectFill
    logoImageView.clipsToBounds = true
    logoImageView.translatesAutoresizingMaskIntoConstraints = false

    view.insertSubview(logoImageView, belowSubview: navigationBar)
    NSLayoutConstraint.activate([
      logoImageView.leftAnchor.constraint(equalTo: view.leftAnchor),
      logoImageView.rightAnchor.constraint(equalTo: view.rightAnchor),
      logoImageView.topAnchor.constraint(equalTo: view.topAnchor),
      logoImageView.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor)
    ])
  }
}
Run Code Online (Sandbox Code Playgroud)