如何在UIDocumentPicker的导航栏中设置图片?
给UIDocumentPicker导航栏添加自定义图片的解决方案
嘿,我看你在尝试给系统的UIDocumentPickerViewController导航栏加自定义标题图片,直接在初始化后设置navigationItem.titleView大概率不会生效——因为系统的文档选择器导航控制器是内部管理的,初始化阶段它的导航栏还没完全配置好。下面给你两种可行的方案:
方案一:用导航控制器代理延迟设置(推荐)
这种方法最可靠,我们等导航控制器完全加载后再修改:
- 先让你的视图控制器遵守
UINavigationControllerDelegate协议:
class YourViewController: UIViewController, UINavigationControllerDelegate { // ... 你的其他代码逻辑 }
- 初始化文档选择器时,把它的导航控制器代理设为当前视图控制器:
let documentPicker = UIDocumentPickerViewController(documentTypes: ["com.adobe.pdf","com.apple.rtfd"], in: .import) documentPicker.navigationController?.delegate = self present(documentPicker, animated: true)
- 实现导航控制器的
willShow方法,在这里配置标题视图和导航栏样式:
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) { // 确认当前显示的是文档选择器页面 guard viewController is UIDocumentPickerViewController else { return } // 先配置导航栏基础样式 navigationController.navigationBar.isTranslucent = false navigationController.navigationBar.tintColor = .black navigationController.navigationBar.backgroundColor = .white // 创建标题图片的容器和图片视图 let logoContainer = UIView() logoContainer.translatesAutoresizingMaskIntoConstraints = false let imageView = UIImageView() imageView.translatesAutoresizingMaskIntoConstraints = false imageView.contentMode = .scaleAspectFill imageView.clipsToBounds = true // 防止图片超出容器 // 加载图片(注意:原代码的图片路径写法有误,正确方式如下) if let logo = UIImage(named: "xyz.me", in: Bundle(for: Self.self), compatibleWith: nil) { imageView.image = logo } logoContainer.addSubview(imageView) // 用AutoLayout替代frame,适配所有设备 NSLayoutConstraint.activate([ imageView.leadingAnchor.constraint(equalTo: logoContainer.leadingAnchor), imageView.trailingAnchor.constraint(equalTo: logoContainer.trailingAnchor), imageView.topAnchor.constraint(equalTo: logoContainer.topAnchor), imageView.bottomAnchor.constraint(equalTo: logoContainer.bottomAnchor), logoContainer.widthAnchor.constraint(equalToConstant: 200), logoContainer.heightAnchor.constraint(equalTo: navigationController.navigationBar.heightAnchor) ]) // 设置标题视图 viewController.navigationItem.titleView = logoContainer }
方案二:present后异步设置(简单但依赖时机)
如果不想用代理,也可以在present文档选择器后,稍微延迟一点再修改导航栏——这种方法简单但依赖系统加载速度,不如代理稳定:
let documentPicker = UIDocumentPickerViewController(documentTypes: ["com.adobe.pdf","com.apple.rtfd"], in: .import) present(documentPicker, animated: true) { // 延迟0.1秒,等导航栏初始化完成 DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { guard let navController = documentPicker.navigationController else { return } // 配置导航栏样式 navController.navigationBar.isTranslucent = false navController.navigationBar.tintColor = .black navController.navigationBar.backgroundColor = .white // 创建标题视图(同样用AutoLayout更稳妥) let logoContainer = UIView() logoContainer.translatesAutoresizingMaskIntoConstraints = false let imageView = UIImageView() imageView.translatesAutoresizingMaskIntoConstraints = false imageView.contentMode = .scaleAspectFill imageView.clipsToBounds = true if let logo = UIImage(named: "xyz.me", in: Bundle(for: YourViewController.self), compatibleWith: nil) { imageView.image = logo } logoContainer.addSubview(imageView) NSLayoutConstraint.activate([ imageView.leadingAnchor.constraint(equalTo: logoContainer.leadingAnchor), imageView.trailingAnchor.constraint(equalTo: logoContainer.trailingAnchor), imageView.topAnchor.constraint(equalTo: logoContainer.topAnchor), imageView.bottomAnchor.constraint(equalTo: logoContainer.bottomAnchor), logoContainer.widthAnchor.constraint(equalToConstant: 200), logoContainer.heightAnchor.constraint(equalTo: navController.navigationBar.heightAnchor) ]) documentPicker.navigationItem.titleView = logoContainer } }
关键注意点
- 图片加载路径:原代码里
UIImage(named: "Resource.bundle/xyz.me")的写法错误,正确的方式是把bundle作为参数传入,所以用UIImage(named: "xyz.me", in: Bundle(for: Self.self), compatibleWith: nil)即可(前提是你的Resource.bundle和当前视图控制器在同一个Target里)。 - AutoLayout替代Frame:用约束布局比固定frame更适配不同尺寸的设备和导航栏高度,避免出现图片显示不全的问题。
- 导航栏样式统一:如果需要修改返回按钮的颜色,直接设置
navigationController.navigationBar.tintColor就可以,不用单独修改leftBarButtonItem的tintColor。
内容的提问来源于stack exchange,提问作者swapnil tilkari
相关产品推荐
相关产品推荐

