使NavigationBar的titleView大于其自身 [英] Make NavigationBar's titleView larger than itself

查看:53
本文介绍了使NavigationBar的titleView大于其自身的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

但是,一旦我按下另一个控制器并弹出,我的ImageView就会再次被裁剪为NavigationBar的大小.

关于如何防止裁剪的任何想法?

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

 覆盖功能funD viewDidLoad(){super.viewDidLoad()让徽标= UIImage(名称:徽标")让titleView = UIView(frame:CGRect(x:0,y:0,width:60,height:60))让imageView = UIImageView(图像:徽标)imageView.frame = CGRect(x:0,y:0,宽度:titleView.frame.width,高度:titleView.frame.height)titleView.addSubview(imageView)imageView.contentMode = .scaleAspectFitimageView.image =徽标navigationItem.titleView = titleView} 

当前有一个临时解决方案,该解决方案使用观察者来覆盖引起问题的视图的clipsToBounds属性:

第一次,当您更改 navigationItem.titleView 时. _UINavigationBarContentView.clipsToBounds false .但是在您按下另一个控制器并弹出后, _UINavigationBarContentView.clipsToBounds true .这就是为什么 titleView 被裁剪的原因.

所以我有一个临时解决方案.每次当 viewController 出现时,找到该视图并将 _UINavigationBarContentView.clipsToBounds 更改为 false 并布局 titleView .

 覆盖功能funD viewDidAppear(_动画:布尔){用于视图:(navigationController?.navigationBar.subviews)中的UIView!{view.clipsToBounds = false;}navigationItem.titleView?.layoutIfNeeded()}覆盖func viewWillAppear(_动画:布尔){用于视图:(navigationController?.navigationBar.subviews)中的UIView!{view.clipsToBounds = false;}navigationItem.titleView?.layoutIfNeeded()} 

我尝试了,而且行得通.但是我认为您不应该这样做,因为这是私人观点.也许苹果不希望我们对此做任何事情.

希望我的建议可以为您提供帮助.祝你好运;)

解决方案

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

 覆盖功能funD viewDidLoad(){super.viewDidLoad()//加载视图后进行其他任何设置,通常是从笔尖进行.让徽标= UIImage(名称:徽标")让titleView = UIView(frame:CGRect(x:0,y:0,width:60,height:60))让imageView = UIImageView(图像:徽标)imageView.frame = CGRect(x:0,y:0,宽度:titleView.frame.width,高度:titleView.frame.height)titleView.addSubview(imageView)imageView.contentMode = .scaleAspectFitimageView.image =徽标navigationItem.titleView = titleViewnavigationController?.navigationBar.subviews [2] .addObserver(自己,forKeyPath:"clipsToBounds",选项:[.old,.new],上下文:nil)}覆盖函数funcValueValue(forKeyPath keyPath:String ?,对象:Any ?,更改:[NSKeyValueChangeKey:Any] ?,上下文:UnsafeMutableRawPointer?){如果(navigationController?.navigationBar.subviews [2] .isEqual(object))!{DispatchQueue.main.async {self.navigationController?.navigationBar.subviews [2] .clipsToBounds = falseself.navigationItem.titleView?.layoutIfNeeded()}}}取消初始化{navigationController?.navigationBar.subviews [2] .removeObserver(自己,forKeyPath:"clipsToBounds")} 

更详细,更轻松的操作,可以在这里查看我的演示 https://github.com/trungducc/stackoverflow/tree/big-title-navigation-bar

I want to place an image in the middle of a navigation bar that is bigger then the bar itself. So far I tried to use a UIView with a UIImageView inside and it works quite well as you can see here:

However as soon as I push another controller and pop back my ImageView gets cropped to the size of the NavigationBar again.

Any ideas on how to prevent the cropping?

My code so far for 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
}

Edit: Currently there is a temporary solution which uses an observer to overwrite the clipsToBounds property of the view that causes the trouble: Link (shout out to @trungduc for that)

解决方案

I found why you got this issue. It's because of a private view which has name _UINavigationBarContentView. It's a subview of UINavigationBar. navigationItem.titleView is contained in this view.

At first time, when you change navigationItem.titleView. _UINavigationBarContentView.clipsToBounds is false .But after you push another controller and pop back, _UINavigationBarContentView.clipsToBounds is true. That's why titleView is cropped.

So i have a temporary solution. Each time when viewController appears, find this view and change _UINavigationBarContentView.clipsToBounds to false and layout 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()
  }

I tried and it works. But i think you shouldn't do something whit it because it's private view. Maybe Apple don't want us do anything with it.

Hope somehow my suggestion can help you. Good luck ;)

SOLUTION

Adding observer for _UINavigationBarContentView.clipsToBounds, each time when it changes to false, set to true and update layout of 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")
}

For more detail and easier, you can check my demo here https://github.com/trungducc/stackoverflow/tree/big-title-navigation-bar

这篇关于使NavigationBar的titleView大于其自身的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆