使NavigationBar的titleView大于其自身

时间:2017-11-05 12:13:59

标签: ios swift uikit

我想将图像放在导航栏的中间,该导航栏比栏本身大。到目前为止,我尝试使用内部有UIImageView的UIView,它可以很好地工作,你可以在这里看到:

enter image description here

然而,只要我按下另一个控制器并弹回我的ImageView就会再次被裁剪为NavigationBar的大小。

enter image description here 关于如何防止裁剪的任何想法?

到目前为止我的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
}

修改目前有一个临时解决方案,它使用观察者覆盖导致问题的视图的clipsToBounds属性:Link(喊出来到@trungduc那个)

3 个答案:

答案 0 :(得分:4)

我找到了你为什么遇到这个问题。这是因为私有视图的名称为_UINavigationBarContentView。这是UINavigationBar的子视图。此视图中包含navigationItem.titleView

enter image description here

第一次更改navigationItem.titleView时。 _UINavigationBarContentView.clipsToBoundsfalse。但是在您推送另一个控制器并弹出后,_UINavigationBarContentView.clipsToBoundstrue。这就是titleView被裁剪的原因。

所以我有一个临时解决方案。每次出现viewController时,都会找到此视图并将_UINavigationBarContentView.clipsToBounds更改为false和布局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()
  }

我尝试了它的确有效。但我认为你不应该做些什么,因为它是私人观点。也许Apple不希望我们用它做任何事情。

希望我的建议可以帮到你。祝你好运;)

<强>解

_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")
}

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

答案 1 :(得分:1)

如果您想要一个自定义高度,但UINavigationBar具有UIBarMetrics,但它不是完全交互式的。

苹果建议a bunch of code实际开发像iMessage app这样的好东西。

答案 2 :(得分:0)

您可以尝试将代码放在viewWillAppear方法中。这样,每次出现视图时,您都会将图像添加到条形图中。但是,您应该在viewDidDissappear方法中删除inageview。如果你需要在几个视图中,你可以继承UIViewController并使用它。