#import <UIKit/UIKit.h>
@interface NavigationController : UINavigationController
// 设置为YES即显示菊花,设置为NO即隐藏菊花
@property (nonatomic, assign) BOOL animate;
@end
#import "NavigationController.h"
@interface NavigationController ()
@property (nonatomic, strong, nullable) UIActivityIndicatorView *indicatorView;
@end
@implementation NavigationController
- (void)viewDidLoad {
[super viewDidLoad];
// 导航栏颜色(白色)
self.navigationBar.barTintColor = [UIColor whiteColor];
// 导航栏title颜色(黑色)
[self.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor blackColor]}];
// 导航栏返回按钮字体颜色(黑色)
self.navigationBar.tintColor = [UIColor blackColor];
// 灰色菊花
self.indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyleGray)];
[self.navigationBar addSubview:self.indicatorView];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
// 进入新页面,title长度变化后,重新调整菊花位置
// Xcode 9编辑器,请用如下代码,兼容iOS8-iOS11
for (UIView *subView in self.navigationBar.subviews) {
if ([NSStringFromClass([subView class]) isEqualToString:@"_UINavigationBarContentView"]) {
for (UIView *sub in subView.subviews) {
if ([sub isKindOfClass:[UILabel class]] && [[sub valueForKey:@"text"] isEqualToString:self.viewControllers.lastObject.title]) {
self.indicatorView.frame = CGRectMake(sub.frame.origin.x - 30, 0, 30, 30);
self.indicatorView.center = CGPointMake(self.indicatorView.center.x, sub.center.y);
}
}
} else if ([NSStringFromClass([subView class]) isEqualToString:@"UINavigationItemView"]) {
if ([[subView valueForKey:@"title"] isEqualToString:[self.viewControllers lastObject].title]) {
self.indicatorView.frame = CGRectMake(subView.frame.origin.x - 30, 0, 30, 30);
self.indicatorView.center = CGPointMake(self.indicatorView.center.x, subView.center.y);
}
}
}
// Xcode 8及以下编辑器,请用如下代码,兼容iOS8-iOS11
for (UIView *subView in self.navigationBar.subviews) {
if ([NSStringFromClass([subView class]) containsString:@"UINavigationItemView"]) {
if ([[subView valueForKey:@"title"] isEqualToString:[self.viewControllers lastObject].title]) {
self.indicatorView.frame = CGRectMake(subView.frame.origin.x - 30, 0, 30, 30);
self.indicatorView.center = CGPointMake(self.indicatorView.center.x, subView.center.y);
}
}
}
}
- (void)setAnimate:(BOOL)animate {
_animate = animate;
if (animate) {
[self.indicatorView startAnimating];
} else {
[self.indicatorView stopAnimating];
}
}
@end
注意:此方法有2个BUG:
BUG:由后面控制器边缘滑动返回前面控制器时,撤销返回后,菊花位置会排在前一个页面的title前面。
解决办法:项目所有控制器继承自自定义控制器BaseViewController,在BaseViewController的viewDidAppear方法中调用导航控制器的viewDidLayoutSubviews方法。
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.navigationController viewDidLayoutSubviews];
}
BUG:还是菊花的位置问题,如果相邻的两个控制器的title都比较长,这时如果返回按钮和title的位置间隔小于30,菊花会和返回按钮重合
解决办法:无(逻辑过于复杂,我选择把title设置短一些😂)
网友评论