使 NavigationBar 的 titleView 比自身大

pal*_*lme 6 uikit ios swift

我想在导航栏的中间放置一个比导航栏本身大的图像。到目前为止,我尝试将 UIView 与 UIImageView 一起使用,并且效果很好,正如您在此处看到的:

在此处输入图片说明

但是,只要我推另一个控制器并弹出我的 ImageView 就会再次裁剪为 NavigationBar 的大小。

在此处输入图片说明 关于如何防止裁剪的任何想法?

到目前为止,我的 iOS 11 代码:

override func viewDidLoad() {
    super.viewDidLoad()

    let logo = UIImage(named: "Logo")
    let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 60, height: 60))
    let imageView = UIImageView(image: logo)
    imageView.frame = CGRect(x: 0, y: 0, width: titleView.frame.width, height: titleView.frame.height)
    titleView.addSubview(imageView)
    imageView.contentMode = .scaleAspectFit
    imageView.image = logo
    navigationItem.titleView = titleView
}
Run Code Online (Sandbox Code Playgroud)

编辑:目前有一个临时解决方案,它使用观察者覆盖导致问题的视图的 clipsToBounds 属性:链接(为此向@trungduc 大喊)

tru*_*duc 6

我找到了你遇到这个问题的原因。这是因为有一个名为 name 的私有视图_UINavigationBarContentView。它是 的子视图UINavigationBarnavigationItem.titleView包含在这个视图中。

在此输入图像描述

第一次,当你改变的时候navigationItem.titleView_UINavigationBarContentView.clipsToBoundsfalse。但是当您按下另一个控制器并弹出后,_UINavigationBarContentView.clipsToBoundstrue。这就是为什么titleView被裁剪的原因。

所以我有一个临时解决方案。每次viewController出现时,找到该视图并更改_UINavigationBarContentView.clipsToBoundsfalse和 布局titleView

override func viewDidAppear(_ animated: Bool) {
    for view : UIView in (navigationController?.navigationBar.subviews)! {
      view.clipsToBounds = false;
    }
    navigationItem.titleView?.layoutIfNeeded()
  }

  override func viewWillAppear(_ animated: Bool) {
    for view : UIView in (navigationController?.navigationBar.subviews)! {
      view.clipsToBounds = false;
    }
    navigationItem.titleView?.layoutIfNeeded()
  }
Run Code Online (Sandbox Code Playgroud)

我尝试过并且有效。但我认为你不应该这样做,因为这是私人观点。也许苹果不想让我们用它做任何事。

希望我的建议能对你有所帮助。祝你好运 ;)

解决方案

添加观察者_UINavigationBarContentView.clipsToBounds,每次更改为 时false,设置为true并更新布局titleView

override func viewDidLoad() {
  super.viewDidLoad()
  // Do any additional setup after loading the view, typically from a nib.

  let logo = UIImage(named: "Logo")
  let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 60, height: 60))
  let imageView = UIImageView(image: logo)
  imageView.frame = CGRect(x: 0, y: 0, width: titleView.frame.width, height: titleView.frame.height)
  titleView.addSubview(imageView)
  imageView.contentMode = .scaleAspectFit
  imageView.image = logo
  navigationItem.titleView = titleView
  navigationController?.navigationBar.subviews[2].addObserver(self, forKeyPath: "clipsToBounds", options: [.old, .new], context: nil)
}

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
  if  (navigationController?.navigationBar.subviews[2].isEqual(object))! {
    DispatchQueue.main.async {
      self.navigationController?.navigationBar.subviews[2].clipsToBounds = false
      self.navigationItem.titleView?.layoutIfNeeded()
    }
  }
}

deinit {
  navigationController?.navigationBar.subviews[2].removeObserver(self, forKeyPath: "clipsToBounds")
}
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息和更简单的信息,您可以在此处查看我的演示https://github.com/trungducc/stackoverflow/tree/big-title-navigation-bar