最近因为项目的需要,需要设计类似与网易一样,每个控制器都能携带一个自己的导航栏,下面就是代码(打字太多,觉得自己都不是一个合格的程序猿,ps:本来有很多废话的,哈哈~~~).
IMG_3906.PNG集成这种功能,只要导入如下图所示的文件,接下来你会发现的你的项目已经实现了类似如网易导航栏的效果,效果如下,我并没有在项目中对控制器本身做任何特殊的处理
3784FC4F-BE34-4B66-BABB-527BA0D5E8B4.png 2017-05-17 23_16_20.gif
下面说下思路:
1.代码1:
// UIViewController+ExtendNavigation.m
+ (void)load
{
// viewWillAppear方法交换
{
IMP imp1 = class_getMethodImplementation([self class], @selector(viewWillAppear:));
Method m1 = class_getInstanceMethod([self class], @selector(viewWillAppear:));
Method m2 = class_getInstanceMethod([self class], @selector(viewWillAppear_QF:));
BOOL result = class_addMethod([self class], @selector(viewWillAppear:), imp1, method_getTypeEncoding(m1));
if (result != YES)
{
method_exchangeImplementations(m1, m2);
}
}
// 交换导航栏标题的方法
{
IMP imp1 = class_getMethodImplementation([self class], @selector(setTitle:));
Method m1 = class_getInstanceMethod([self class], @selector(setTitle:));
Method m2 = class_getInstanceMethod([self class], @selector(setTitle_QF:));
BOOL result = class_addMethod([self class], @selector(setTitle:), imp1, method_getTypeEncoding(m1));
if (result != YES)
{
method_exchangeImplementations(m1, m2);
}
}
}
代码2:
- (void)viewWillAppear_QF:(BOOL)animated {
[self viewWillAppear_QF:animated];
if (self.loadNavigationBar)
{
NSLog(@"%@",self);
// 自定义导航栏
[self styleNavBar];
self.navigationItem.viewController = self;
__weak id weakSelf = self;
self.navigationController.interactivePopGestureRecognizer.delegate = weakSelf;
}
self.loadNavigationBar = NO;
}
- (void)styleNavBar {
[self.navigationController setNavigationBarHidden:YES animated:NO];
_QFNavigationBar * newNavBar = self.navigationBar;
[self.view addSubview:newNavBar];
}
- (_QFNavigationBar *)navigationBar
{
_QFNavigationBar *navigationBar = objc_getAssociatedObject(self, @selector(navigationBar));
if (!navigationBar) {
navigationBar = [[_QFNavigationBar alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 64.0)];
[navigationBar setItems:@[self.navigationItem]];
[self setNavigationBar:navigationBar];
}
return navigationBar;
}
- (_QFNavigationItem *)navigationItem
{
_QFNavigationItem * item = objc_getAssociatedObject(self, _cmd);
if (!item){
item = [[_QFNavigationItem alloc]init];
[self setNavigationItem:item];
}
return item;
}
代码3:
- (void)setTitle_QF:(NSString *)title
{
[self setTitle_QF:title];
self.navigationItem.title = title;
}
从代码2和代码3相信大家也能看出来,我为什么要对这两个函数进行交换,还是解释下代码2是为了保证添加的导航栏在控制器中,视图层级是最高的(ps如果你不乱写),代码3则是为了保证设置控制器标题的时候能够拦截下来,便于显示在我们自定义的导航栏上面.
此外:loadNavigationBar
是表示这个控制器是否应该加载导航栏控制器,这个标志会在被push函数中被置为YES,下面是代码
@interface UINavigationController (ExtendNavigation)
@end
@implementation UINavigationController (ExtendNavigation)
+ (void)load
{
Method originalMethod = class_getInstanceMethod(self, @selector(pushViewController:animated:));
Method swizzledMethod = class_getInstanceMethod(self, @selector(qf_pushViewController:animated:));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
- (void)qf_pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
viewController.loadNavigationBar = YES;
[self qf_pushViewController:viewController animated:animated];
}
ps:_QFNavigationBar
是我自定义继承自UINavigationBar
的一个类,我们可以在这个类的初始化方法体里面,配置我们导航栏APP主题风格方式,而在_QFNavigationItem
,我们可以定制导航栏返回函数,以及按钮图片,下面是具体的代码
#import "_QFNavigationBar.h"
// 缺省情况下导航栏的颜色
#define kDefaultNavigationBar [UIColor whiteColor]
@implementation _QFNavigationBar
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.barTintColor = kDefaultNavigationBar;
}
return self;
}
@end
#import "_QFNavigationItem.h"
@implementation _QFNavigationItem
- (void)setViewController:(UIViewController *)viewController
{
_viewController = viewController;
if (self.viewController.navigationController.viewControllers.count>1)
{
UIImage *backButtonImage = [UIImage imageNamed:@"icon_nav_back"];
UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithImage:backButtonImage style:UIBarButtonItemStylePlain target:self action:@selector(backTapped:)];
self.leftBarButtonItem = backBarButtonItem;
}
}
- (void)backTapped:(id)sender {
[self.viewController.navigationController popViewControllerAnimated:YES];
}
@end
OK,搞定!一切尽在代码中(原谅我不善表达/(ㄒoㄒ)/~~)
最后附上Demo项目地址:https://github.com/ZYCoderIOS/ExtendNavigation
网友评论