简体   繁体   English

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

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

I'm using an image view to display an image in my nav bar. 我正在使用图像视图在导航栏中显示图像。 The problem is that I can't set it to the center correctly because of the back button. 问题是由于后退按钮我无法正确设置它。 I checked the related questions and had almost the same problem earlier that I solved, but this time I have no idea. 我检查了相关问题,并且在我解决之前遇到了几乎相同的问题,但这次我不知道。

Earlier I solved this problem with fake bar buttons, so I tried to add a fake bar button to the right (and left) side, but it doesn't helped. 之前我用假条形按钮解决了这个问题,所以我尝试在右侧(和左侧)添加假条形按钮,但它没有帮助。

- (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];

}

I think it should be workin fine because in this case the titleView has bar buttons on the same side. 我认为它应该工作正常,因为在这种情况下titleView在同一侧有条形按钮。 Is there any explanation why it worked with bar buttons that was created programmatically but doesn't works with the common back button? 是否有任何解释为什么它可以使用以编程方式创建但不能与常用后退按钮一起使用的条形按钮?

UINavigationBar automatically centers its titleView as long as there is enough room. 只要有足够的空间, UINavigationBar自动将其titleView If the title isn't centered that means that the title view is too wide to be centered, and if you set the backgroundColor if your UIImageView you'll see that's exactly what is happening. 如果标题不居中意味着标题视图太宽而无法居中,如果您设置了backgroundColor,如果您的UIImageView您将看到正是发生的事情。

The title view is too wide because that navigation bar will automatically resize the title to hold its content, using -sizeThatFits: . 标题视图太宽,因为导航栏会自动调整标题大小以保存其内容,使用-sizeThatFits: . This means that your title view will always be resized to the size of your image. 这意味着您的标题视图将始终调整为图像大小。

Two possible fixes: 两个可能的修复:

  1. The image you're using is way too big. 你正在使用的图像太大了。 Use a properly sized 44x44 pt image with 2x and 3x versions. 使用尺寸合适的44x44 pt图像,2x和3x版本。

  2. Wrap UIImageView inside of a regular UIView to avoid resizing. 在常规UIView中包装UIImageView以避免调整大小。

Example: 例:

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;

An example in Swift 3 version of Darren's second way: Swren 3版Darren第二种方式的一个例子:

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

I suggest you Override the function - (void)setFrame:(CGRect)fram like this: 我建议你覆盖函数 - (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 

}

so that the titleView.center always the right location 这样titleView.center始终是正确的位置

Don't use titleView. 不要使用titleView。

Just add your image to navigationController.navigationBar 只需将您的图像添加到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];

Qun Li's worked perfectly for me. 群力对我很有帮助。 Here's the swift 2.3 code: 这是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
    }
}

如果您正在使用笔尖中的自定义视图,请确保在nib文件上禁用自动布局。

I created a custom UINavigationController that after dropping in, the only thing you have to do is call showNavBarTitle(title:font:) when you want to show and removeNavBarTitle() when you want to hide: 我创建了一个自定义的UINavigationController ,在你想要隐藏时,你想要显示和removeNavBarTitle()时,你唯一需要做的就是调用showNavBarTitle(title:font:)

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()
    }
}

I find the best place to call showNavBarTitle(title:font:) and removeNavBarTitle() are in the view controller's viewWillAppear() and viewWillDisappear() methods, respectively: 我发现调用showNavBarTitle(title:font:)removeNavBarTitle()的最佳位置分别位于视图控制器的viewWillAppear()viewWillDisappear()方法中:

class YourViewController: UIViewController {

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

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

1) You can try setting your image as UINavigationBar's background image by calling 1)您可以尝试通过调用将图像设置为UINavigationBar的背景图像

[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"color.png"] forBarMetrics:UIBarMetricsDefault];

inside the viewDidLoad method. viewDidLoad方法中。

That way it will be always centered, but if you have back button with long title as left navigation item, it can appear on top of your logo. 这样它将始终居中,但如果您有带有长标题的back按钮作为左侧导航项,它可以显示在您的徽标顶部。 And you should probably at first create another image with the same size as the navigation bar, then draw your image at its center, and after that set it as the background image. 您可能应该首先创建与导航栏大小相同的另一个图像,然后在其中心绘制图像,然后将其设置为背景图像。

2) Or instead of setting your image view as titleView , you can try simply adding at as a subview, so it won't have the constraints related to right and left bar button items. 2)或者不是将图像视图设置为titleView ,您可以尝试简单地将其添加为子视图,因此它不会具有与右侧和左侧条形按钮项相关的约束。

In Swift, this is what worked for me however it´s not the best solution (basically, add it up to navigationBar): 在Swift中,这对我有用,但它不是最好的解决方案(基本上,将它添加到navigationBar):

    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

      }

Extending Darren's answer, a fix for me was to return a sizeThatFits with the UILabel size. 扩展Darren的答案,对我来说一个修复就是返回一个尺寸为UILabel大小的sizeThatFits It turns out that this is called after layoutSubViews so the label has a size. 事实证明,这是在layoutSubViews之后调用的,因此标签有一个大小。

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

Also note that I have + titleInset*2 because Im setting the horizontal constraints like so: 还要注意我有+ titleInset*2因为我设置了水平约束,如下所示:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM