无法在导航栏中心设置 titleView,因为后退按钮

Can't set titleView in the center of navigation bar because back button

我正在使用图像视图在我的导航栏中显示图像。问题是由于后退按钮,我无法将其正确设置到中心。我查了相关问题,和我之前解决的问题几乎一样,但是这次我不知道。

之前我用假的条形按钮解决了这个问题,所以我尝试在右侧(和左侧)添加一个假的条形按钮,但没有帮助。

- (void) searchButtonNavBar {


    CGRect imageSizeDummy = CGRectMake(0, 0, 25,25);

    UIButton *dummy = [[UIButton alloc] initWithFrame:imageSizeDummy];

    UIBarButtonItem
    *searchBarButtonDummy =[[UIBarButtonItem alloc] initWithCustomView:dummy];
    self.navigationItem.rightBarButtonItem = searchBarButtonDummy;

}


- (void)setNavBarLogo {

    [self setNeedsStatusBarAppearanceUpdate];
    CGRect myImageS = CGRectMake(0, 0, 44, 44);
    UIImageView *logo = [[UIImageView alloc] initWithFrame:myImageS];
    [logo setImage:[UIImage imageNamed:@"color.png"]];
    logo.contentMode = UIViewContentModeScaleAspectFit;
    self.navigationItem.titleView = logo;
    [[UIBarButtonItem appearance] setTitlePositionAdjustment:UIOffsetMake(0.0f, 0.0f) forBarMetrics:UIBarMetricsDefault];

}

我认为它应该可以正常工作,因为在这种情况下 titleView 在同一侧有条形按钮。是否有任何解释为什么它适用于以编程方式创建但不适用于通用后退按钮的条形按钮?

1) 您可以尝试通过调用

将您的图像设置为 UINavigationBar 的背景图像
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"color.png"] forBarMetrics:UIBarMetricsDefault];

viewDidLoad 方法中。

这样它将始终居中,但如果您有 back 带有长标题的按钮作为左侧导航项,它可以显示在徽标的顶部。你可能应该首先创建另一个与导航栏大小相同的图像,然后在其中心绘制你的图像,然后将其设置为背景图像。

2) 或者不要将图像视图设置为 titleView,您可以尝试简单地将 at 添加为子视图,这样它就不会具有与左右栏按钮项目相关的约束。

不要使用 titleView。

只需将您的图片添加到 navigationController.navigationBar

CGRect myImageS = CGRectMake(0, 0, 44, 44);
UIImageView *logo = [[UIImageView alloc] initWithFrame:myImageS];
[logo setImage:[UIImage imageNamed:@"color.png"]];
logo.contentMode = UIViewContentModeScaleAspectFit;
logo.center = CGPointMake(self.navigationController.navigationBar.width / 2.0, self.navigationController.navigationBar.height / 2.0);
logo.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
[self.navigationController.navigationBar addSubview:logo];
只要有足够的空间,

UINavigationBar 就会自动将其 titleView 居中。如果标题未居中,则意味着标题视图太宽而无法居中,如果您设置了 backgroundColor UIImageView,您会看到这正是正在发生的事情。

标题视图太宽,因为导航栏会自动调整标题大小以容纳其内容,使用 -sizeThatFits:。这意味着您的标题视图将始终调整为图像的大小。

两个可能的修正:

  1. 您使用的图片太大了。使用具有 2x 和 3x 版本的适当大小的 44x44 pt 图像。

  2. 将 UIImageView 包裹在常规 UIView 中以避免调整大小。

示例:

UIImageView* imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"test.jpeg"]];
imageView.contentMode = UIViewContentModeScaleAspectFit;

UIView* titleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
imageView.frame = titleView.bounds;
[titleView addSubview:imageView];

self.navigationItem.titleView = titleView;

如果您使用的是来自 nib 的自定义视图,请务必禁用 nib 文件的自动布局。

我建议你覆盖函数 - (void)setFrame:(CGRect)fram 像这样:

- (void)setFrame:(CGRect)frame  { 

    [super setFrame:frame]; //systom function

    self.center = CGPointMake(self.superview.center.x, self.center.y);   //rewrite function 

}

以便 titleView.center 始终位于正确的位置

Swift3版本达伦第二种方式的例子:

let imageView = UIImageView(image: UIImage(named: "test"))
    imageView.contentMode = UIViewContentMode.scaleAspectFit
let titleView = UIView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
    imageView.frame = titleView.bounds
    titleView.addSubview(imageView)

self.navigationItem.titleView = titleView

Qun Li 非常适合我。这是 swift 2.3 代码:

override var frame: CGRect {
    set(newValue) {
        super.frame = newValue

        if let superview = self.superview {
            self.center = CGPoint(x: superview.center.x, y: self.center.y)
        }
    }

    get {
        return super.frame
    }
}

我创建了一个自定义 UINavigationController,在加入后,您唯一需要做的就是在您想要显示时调用 showNavBarTitle(title:font:),在您想要隐藏时调用 removeNavBarTitle()

class NavigationController: UINavigationController {

    private static var mTitleFont = UIFont(name: <your desired font (String)> , size: <your desired font size -- however, font size will automatically adjust so the text fits in the label>)!
    private static var mNavBarLabel: UILabel = {

        let x: CGFloat = 60
        let y: CGFloat = 7
        let label = UILabel(frame: CGRect(x: x, y: y, width: UIScreen.main.bounds.size.width - 2 * x, height: 44 - 2 * y))

        label.adjustsFontSizeToFitWidth = true
        label.minimumScaleFactor = 0.5
        label.font = NavigationController.mTitleFont
        label.numberOfLines = 0
        label.textAlignment = .center

        return label
    }()

    func showNavBarLabel(title: String, font: UIFont = mTitleFont) {
        NavigationController.mNavBarLabel.text = title
        NavigationController.mNavBarLabel.font = font
        navigationBar.addSubview(NavigationController.mNavBarLabel)
    }

    func removeNavBarLabel() {
        NavigationController.mNavBarLabel.removeFromSuperview()
    }
}

我发现调用 showNavBarTitle(title:font:)removeNavBarTitle() 的最佳位置分别是在视图控制器的 viewWillAppear()viewWillDisappear() 方法中:

class YourViewController: UIViewController {

    func viewWillAppear() {
        (navigationController as! NavigationController).showNavBarLabel(title: "Your Title")
    }

    func viewWillDisappear() {
        (navigationController as! NavigationController).removeNavBarLabel()
    }
}

在 Swift 中,这对我有用,但它不是最佳解决方案(基本上,将其添加到导航栏):

    let titleIV = UIImageView(image: UIImage(named:"some"))
        titleIV.contentMode = .scaleAspectFit
        titleIV.translatesAutoresizingMaskIntoConstraints = false

      if let navigationController = self.navigationController{
            navigationController.navigationBar.addSubview(titleIV)
            titleIV.centerXAnchor.constraint(equalTo:  
navigationController.navigationBar.centerXAnchor).isActive = true
            titleIV.centerYAnchor.constraint(equalTo: navigationController.navigationBar.centerYAnchor).isActive = true
      }
      else{
            view.addSubview(titleIV)
            titleIV.topAnchor.constraint(equalTo: view.topAnchor, constant: UIApplication.shared.statusBarFrame.height).isActive = true
            titleIV.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

      }

扩展 Darren 的回答,对我来说,解决方法是 return sizeThatFits 大小 UILabel。事实证明,这是在 layoutSubViews 之后调用的,因此标签具有大小。

override func sizeThatFits(_ size: CGSize) -> CGSize {
    return CGSize(width: titleLabel.frame.width + titleInset*2, height: titleLabel.frame.height)
}

另请注意,我有 + titleInset*2 因为我是这样设置水平约束的:

titleLabel.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: titleInset),
titleLabel.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -titleInset)