ios 由于后退按钮,无法在导航栏的中心设置 titleView

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28121388/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:28:53  来源:igfitidea点击:

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

iosobjective-cuinavigationbar

提问by rihe

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 titleViewhas bar buttons on the same side. Is there any explanation why it worked with bar buttons that was created programmatically but doesn't works with the common back button?

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

回答by Darren

UINavigationBarautomatically centers its titleViewas long as there is enough room. 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 UIImageViewyou'll see that's exactly what is happening.

UINavigationBartitleView只要有足够的空间,它就会自动居中。如果标题未居中,则意味着标题视图太宽而无法居中,如果您设置了 backgroundColor,您UIImageView会看到这正是正在发生的事情。

The title view is too wide because that navigation bar will automatically resize the title to hold its content, using -sizeThatFits:. This means that your title view will always be resized to the size of your image.

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

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.

  2. Wrap UIImageView inside of a regular UIView to avoid resizing.

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

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

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;

回答by pedrouan

An example in Swift 3version of Darren's second way:

Darren 第二种方式的Swift 3版本中的一个示例:

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

回答by Qun Li

I suggest you Override the function - (void)setFrame:(CGRect)fram like this:

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

- (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 始终位于正确的位置

回答by PowHu

Don't use 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];

回答by MikeB

Qun Li's worked perfectly for me. Here's the swift 2.3 code:

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

回答by joslinm

If you're using a custom view from a nib, be sure to disable auto-layout on the nib file.

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

回答by shoe

I created a custom UINavigationControllerthat 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,在插入后,您唯一要做的就是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()
    }
}

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

回答by Francisco José García Villarán

In Swift, this is what worked for me however it′s not the best solution (basically, add it up to navigationBar):

在 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

      }

回答by bzz

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 viewDidLoadmethod.

viewDidLoad方法里面。

That way it will be always centered, but if you have backbutton with long title as left navigation item, it can appear on top of your logo. 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.

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

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,您可以尝试简单地将 at 添加为子视图,而不是将图像视图设置为 ,这样它就不会受到与左右栏按钮项相关的约束。

回答by richy

Extending Darren's answer, a fix for me was to return a sizeThatFitswith the UILabelsize. It turns out that this is called after layoutSubViews so the label has a size.

扩展达伦的回答,对我来说是修复是返回一个sizeThatFitsUILabel大小。事实证明这是在 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*2because 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)