Adjusting navigationItem.titleView's frame?

2019-03-08 15:00发布

I noticed that the titleView's position depends on the rightbarbutton title. How can I set the frame of the titleView to be in the center instead?

I've tried setting titleView.frame, but to no avail.

Here's the code:

UIButton *titleLabel = [UIButton buttonWithType:UIButtonTypeCustom];
[titleLabel setTitle:@"Right Eye" forState:UIControlStateNormal];
[titleLabel setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[titleLabel setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted];
titleLabel.frame = CGRectMake(100, 0, 180, 44);
titleLabel.titleLabel.backgroundColor = [UIColor clearColor];
titleLabel.titleLabel.font = [UIFont boldSystemFontOfSize:20.0];
titleLabel.titleLabel.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.3];
//  titleLabel.titleLabel.textAlignment = UITextAlignmentCenter; (this doesn't work either)
[titleLabel addTarget:self action:@selector(titleTap:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.titleView = titleLabel;
self.navigationItem.titleView.frame = CGRectMake(100, 0, 180, 44); //(this doesn't work either)

alt text

13条回答
爷的心禁止访问
2楼-- · 2019-03-08 15:07

I was implementing a two row title similar to something WhatsApp is doing (title and subtitle).

I fixed this problem by subclassing UINavigationController and overriding viewDidLayoutSubviews().

My titleView looks like the following (in a viewController):

let frame = self.navigationController?.navigationBar.bounds ?? CGRect.zero

// This is a container view for the two labels, laying them out vertically
let titleView = UIStackView(arrangedSubviews: [self._titleLabel, self._promptLabel])
titleView.axis = .vertical
titleView.alignment = .center
titleView.distribution = .fill
titleView.frame = frame // set the frame to the navbarFrame initially
titleView.spacing = 0

// The wrapper is necessary for laying out the stackView as the titleView
let wrapperView = UIView(frame: frame)
wrapperView.addSubview(titleView)

self.navigationItem.titleView = wrapperView

My viewDidLayoutSubviews():

guard let navigationItem = self.topViewController?.navigationItem,
      let titleView = navigationItem.titleView,
      let wrapperView = titleView.subviews[0] as? UIStackView else { return }

var width : CGFloat = 0

for view in wrapperView.arrangedSubviews {
    view.sizeToFit()
    width = max(width, view.frame.size.width)
}

titleView.frame.size.width = width
titleView.frame.size.height = self.navigationBar.frame.height
wrapperView.frame = titleView.bounds
wrapperView.center.x = self.navigationBar.convert(self.navigationBar.center, to: titleView).x
wrapperView.center.y = titleView.frame.height / 2

self.navigationBar.layoutIfNeeded()

Note: The trick is to have a wrapper view around your titleView which can be layed out by the navigation bar. Then adjust the frame of your titleView to what you desire.

查看更多
Deceive 欺骗
3楼-- · 2019-03-08 15:07

Just add invisible button (no text) on right side of navigation bar, and change it size to for example 20 px

查看更多
Fickle 薄情
4楼-- · 2019-03-08 15:09

After setting up your titleView or titleLabel, call sizeToFit on it, also make sure titleLabel.textAlignment = UITextAlignmentCenter. It'll be centered in the width of the navbar rather than in the space between the button edge and far edge of navbar.

查看更多
我欲成王,谁敢阻挡
5楼-- · 2019-03-08 15:09

You can try set the frame to CGRectZero initially and call sizeToFit. Below is the code I used to change the title text and made sure it is still centered. I had a back button on the left.

UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];    
label.text = @"Title";
[label sizeToFit];
self.navigationItem.titleView = label;
查看更多
孤傲高冷的网名
6楼-- · 2019-03-08 15:10
-(void) awakeFromNib
{
    UIButton *titleLabel = [UIButton buttonWithType:UIButtonTypeCustom];
    [titleLabel setTitle:@"Right Eye" forState:UIControlStateNormal];
    [titleLabel setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [titleLabel setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted];
    titleLabel.titleLabel.backgroundColor = [UIColor clearColor];
    titleLabel.titleLabel.font = [UIFont boldSystemFontOfSize:20.0];
    titleLabel.titleLabel.shadowColor = [UIColor colorWithWhite:0.0 alpha:0.3];
    [titleLabel addTarget:self action:@selector(titleTap:) forControlEvents:UIControlEventTouchUpInside];
    titleLabel.frame = CGRectMake(0, 0, 400, 20);
    self.navigationItem.titleView = titleLabel;

}
查看更多
Juvenile、少年°
7楼-- · 2019-03-08 15:12

None of the suggestions here really worked for me. My issue was that I was setting titleView while the navigation bar was in the middle of it's transition - I'd get this weird jitter where the titleView would flicker over to the left, and then end up back in the center.

I ended up following smallduck's idea and overriding setFrame, was as simple as:

- (void)setFrame:(CGRect)frame {
    [super setFrame:CGRectMake(0, 0, self.superview.bounds.size.width, self.superview.bounds.size.height)];
}
查看更多
登录 后发表回答