iOS仿微信和QQ导航栏加菊花转

2017-08-20  本文已影响2472人  _moses
QQ导航栏.png
#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设置短一些😂)

上一篇下一篇

猜你喜欢

热点阅读