具有类似 scaleAspectFill 行为的 UINavigationBar 背景图像
UINavigationBar background image with scaleAspectFill-like behavior
tl;dr
我正在尝试为 UINavigationBar
设置背景图片。有没有办法配置导航栏,使其使用类似 scaleAspectFill
的行为(作为 UIImageView
,contentMode
设置为 scaleAspectFill
)?
目标
我有一张大致适合景观导航栏尺寸的图像 iPhone(64pt 高,大约 800pt 宽;不过这里的确切尺寸应该无关紧要),我用 navigationBar.setBackgroundImage(img, for: .default)
设置了它。该图像是一张模糊的照片,因此不需要像素完美。顺便说一句——我正在使用 UINavigationBar.appearance
一次设置所有导航栏的背景。
我想要它做什么:纵向显示图像的中心部分,横向显示不裁剪的完整图像。如果高度不完全匹配(正如 iPhone X 所预期的那样),它应该放大一点以填充额外的高度。
作为后备解决方案,如果宽度较小的图像居中显示并通过拉伸第一个和最后一个像素列填充额外的水平 space,我也会接受。
到目前为止我尝试了什么
- 目标 1:设置
UINavigationBar
的 contentMode
-- 在渲染图像时似乎被忽略了
- 目标 2:使用较小的图像并通过
stretchableImage(withLeftCapWidth:topCapHeight:)
使其可伸缩——填充导航栏但图像被推到右下角(显然是因为此方法仅将左侧和顶部视为可伸缩边距)
- 目标 2:使用较小的图像并使用
resizableImage(withCapInsets:resizingMode:)
调整大小,resizingMode
设置为 stretch
——在横向模式下它只是将图像拉伸到全宽,忽略cap insets(可能这个方法不符合我的想法)。
您可以尝试将 UIImageView
与 contentMode = .scaleAspectFill
直接添加到 UINavigationBar
中,这样做:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let imgView = UIImageView(image: UIImage(named: "desert"))
imgView.contentMode = .scaleAspectFill
imgView.frame = self.navigationController!.navigationBar.frame
self.navigationController?.navigationBar.addSubview(imgView)
self.navigationController?.navigationBar.sendSubview(toBack: imgView)
}
}
结果是:
通过向 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)
])
}
}
tl;dr
我正在尝试为 UINavigationBar
设置背景图片。有没有办法配置导航栏,使其使用类似 scaleAspectFill
的行为(作为 UIImageView
,contentMode
设置为 scaleAspectFill
)?
目标
我有一张大致适合景观导航栏尺寸的图像 iPhone(64pt 高,大约 800pt 宽;不过这里的确切尺寸应该无关紧要),我用 navigationBar.setBackgroundImage(img, for: .default)
设置了它。该图像是一张模糊的照片,因此不需要像素完美。顺便说一句——我正在使用 UINavigationBar.appearance
一次设置所有导航栏的背景。
我想要它做什么:纵向显示图像的中心部分,横向显示不裁剪的完整图像。如果高度不完全匹配(正如 iPhone X 所预期的那样),它应该放大一点以填充额外的高度。
作为后备解决方案,如果宽度较小的图像居中显示并通过拉伸第一个和最后一个像素列填充额外的水平 space,我也会接受。
到目前为止我尝试了什么
- 目标 1:设置
UINavigationBar
的contentMode
-- 在渲染图像时似乎被忽略了 - 目标 2:使用较小的图像并通过
stretchableImage(withLeftCapWidth:topCapHeight:)
使其可伸缩——填充导航栏但图像被推到右下角(显然是因为此方法仅将左侧和顶部视为可伸缩边距) - 目标 2:使用较小的图像并使用
resizableImage(withCapInsets:resizingMode:)
调整大小,resizingMode
设置为stretch
——在横向模式下它只是将图像拉伸到全宽,忽略cap insets(可能这个方法不符合我的想法)。
您可以尝试将 UIImageView
与 contentMode = .scaleAspectFill
直接添加到 UINavigationBar
中,这样做:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let imgView = UIImageView(image: UIImage(named: "desert"))
imgView.contentMode = .scaleAspectFill
imgView.frame = self.navigationController!.navigationBar.frame
self.navigationController?.navigationBar.addSubview(imgView)
self.navigationController?.navigationBar.sendSubview(toBack: imgView)
}
}
结果是:
通过向 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)
])
}
}