Skip to content

Commit

Permalink
修复 QMUINavigationTitleView 在 iOS 11 下的若干布局问题
Browse files Browse the repository at this point in the history
  • Loading branch information
MoLice committed Jul 25, 2017
1 parent 36b418e commit 270ebd1
Showing 1 changed file with 36 additions and 8 deletions.
44 changes: 36 additions & 8 deletions QMUIKit/UIComponents/QMUINavigationTitleView.m
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@
#import "UIActivityIndicatorView+QMUI.h"
#import "UIView+QMUI.h"

@interface UINavigationBar (QMUI)
@interface UINavigationBar (TitleView)

@end

@implementation UINavigationBar (QMUI)
@implementation UINavigationBar (TitleView)

+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
ReplaceMethod([self class], @selector(layoutSubviews), @selector(qmui_navigationBarLayoutSubviews));
ReplaceMethod([self class], @selector(layoutSubviews), @selector(titleView_navigationBarLayoutSubviews));
});
}

- (void)qmui_navigationBarLayoutSubviews {
- (void)titleView_navigationBarLayoutSubviews {
QMUINavigationTitleView *titleView = (QMUINavigationTitleView *)self.topItem.titleView;

if ([titleView isKindOfClass:[QMUINavigationTitleView class]]) {
Expand All @@ -41,11 +41,18 @@ - (void)qmui_navigationBarLayoutSubviews {
titleView.frame = CGRectMake(CGRectGetMinX(titleView.frame), titleViewMinY, fminf(titleViewMaximumWidth, titleViewSize.width), titleViewSize.height);
// NSLog(@"【%@】修正布局后\ntitleView = %@", NSStringFromClass(titleView.class), titleView);
}

// iOS 11 之后 titleView 的布局发生了一些变化,如果不主动设置宽度,titleView 里的内容就可能无法完整展示
if (IOS_VERSION >= 11.0) {
if (CGRectGetWidth(titleView.bounds) != titleViewSize.width) {
titleView.frame = CGRectSetWidth(titleView.frame, titleViewSize.width);
}
}
} else {
titleView = nil;
}

[self qmui_navigationBarLayoutSubviews];
[self titleView_navigationBarLayoutSubviews];

if (titleView) {
// NSLog(@"【%@】系统布局后\ntitleView = %@", NSStringFromClass(titleView.class), titleView);
Expand Down Expand Up @@ -118,10 +125,26 @@ - (NSString *)description {
#pragma mark - 布局

- (void)refreshLayout {
[self.superview setNeedsLayout];
UINavigationBar *navigationBar = [self navigationBarSuperviewForSubview:self];
if (navigationBar) {
[navigationBar setNeedsLayout];
}
[self setNeedsLayout];
}

// 找到 titleView 所在的 navigationBar(iOS 11 及以后,titleView.superview.superview == navigationBar,iOS 10 及以前,titleView.superview == navigationBar)
- (UINavigationBar *)navigationBarSuperviewForSubview:(UIView *)subview {
if (!subview.superview) {
return nil;
}

if ([subview.superview isKindOfClass:[UINavigationBar class]]) {
return (UINavigationBar *)subview.superview;
}

return [self navigationBarSuperviewForSubview:subview.superview];
}

- (void)updateTitleLabelSize {
if (self.titleLabel.text.length > 0) {
// 这里用 CGSizeCeil 是特地保证 titleView 的 sizeThatFits 计算出来宽度是 pt 取整,这样在 layoutSubviews 我们以 px 取整时,才能保证不会出现水平居中时出现半像素的问题,然后由于我们对半像素会认为一像素,所以导致总体宽度多了一像素,从而导致文字布局可能出现缩略...
Expand Down Expand Up @@ -419,16 +442,21 @@ - (void)setAccessoryType:(QMUINavigationTitleViewAccessoryType)accessoryType {
if (!self.accessoryTypeView) {
self.accessoryTypeView = [[UIImageView alloc] init];
self.accessoryTypeView.contentMode = UIViewContentModeCenter;
[self addSubview:self.accessoryTypeView];
}

UIImage *accessoryImage;
UIImage *accessoryImage = nil;
if (accessoryType == QMUINavigationTitleViewAccessoryTypeDisclosureIndicator) {
accessoryImage = [NavBarAccessoryViewTypeDisclosureIndicatorImage qmui_imageWithOrientation:UIImageOrientationUp];
}

self.accessoryTypeView.image = accessoryImage;
[self.accessoryTypeView sizeToFit];

// 经过上面的 setImage 和 sizeToFit 之后再 addSubview,因为 addSubview 会触发系统来询问你的 sizeThatFits:
if (self.accessoryTypeView.superview != self) {
[self addSubview:self.accessoryTypeView];
}

[self refreshLayout];
}

Expand Down

0 comments on commit 270ebd1

Please sign in to comment.