GithubHelp home page GithubHelp logo

smilezxlee / zxnavigationbar Goto Github PK

View Code? Open in Web Editor NEW
325.0 5.0 56.0 2.83 MB

灵活轻量的自定义导航栏,导航栏属于控制器view,支持导航栏联动,一行代码实现【导航栏背景图片设置、导航栏渐变、折叠、修改Item大小和边距、自定义导航栏高度、全屏手势返回、pop拦截、仿系统导航栏历史堆栈】等各种效果

License: MIT License

Ruby 0.12% Objective-C 97.75% C 2.13%
navigationbar navigationbaritems navigation navigation-bar navigationview

zxnavigationbar's Introduction

ZXNavigationBar

License MIT  CocoaPods  CocoaPods  Support 

安装

通过CocoaPods安装

pod 'ZXNavigationBar'

或手动导入

  • 将ZXNavigationBar拖入项目中。

导入头文件

#import "ZXNavigationBarController.h"

功能&特点

  • 每个控制器单独管理自己的导航栏,导航栏属于控制器的子view,不再属于统一的导航控制器
  • 兼容iOS8-iOS16,兼容刘海屏、药丸屏、iPad等各种设备,适配横竖屏,无需担心系统更新需要重新适配导航栏
  • 仅需一行代码即可轻松设置导航栏背景图片、背景色、导航栏渐变、状态栏颜色、Item大小和边距等各类属性
  • 仅需一行代码即可实现拦截pop手势与点击返回事件,并决定是否要响应pop操作
  • 仅需一行代码即可解决scrollView横向滚动与pop手势冲突问题
  • 支持随时切换为系统导航栏,且与系统导航栏之间无缝衔接
  • 支持自定义ZXNavigationBar高度
  • 支持在ZXNavigationBar上自定义titleView与navItemView
  • ZXNavigationBar自带效果都无法满足,支持任意自定义导航栏View
  • 支持导航栏折叠、支持跟随ScrollView滚动透明度自动改变
  • 支持通过url加载导航栏Item图片
  • 支持全屏手势返回
  • 支持自定义手势返回范围
  • 支持监听手势返回进度
  • 仿系统导航栏历史堆栈效果,支持iOS8-iOS16,支持自定义基本样式
  • 若从Xib中加载控制器View,添加子View无需手动设置距离导航栏顶部约束,ZXNavigationBar会自动处理

反馈&交流qq群:790460711

效果预览

导航栏设置 仿微博热搜效果 自定义导航栏
自定义titleView 兼容scrollView横向滚动 可伸缩式导航栏

开始使用

将控制器继承于ZXNavigationBarController,建议将Base控制器继承于ZXNavigationBarController

@interface DemoBaseViewController : ZXNavigationBarController

@end

【建议,非必须】将导航控制器继承于ZXNavigationBarNavigationController,建议将Base导航控制器继承于ZXNavigationBarNavigationController

@interface DemoBaseNavigationController : ZXNavigationBarNavigationController

@end

【重要】注意事项

  • ZXNavigationBar会自动显示返回按钮,且实现点击pop功能,您无需设置,若需要自定义返回按钮,直接覆盖self.zx_navLeftBtn的图片和点击回调即可
  • 如果项目中存在黑白状态栏交替的需求,建议先在base控制器的viewDidLoad方法中统一设置状态栏颜色,以避免设置成白色状态栏后返回上一个页面无法自动恢复为黑色状态栏
@interface DemoBaseViewController : ZXNavigationBarController
- (void)viewDidLoad{
    [super viewDidLoad];
    self.zx_navStatusBarStyle = ZXNavStatusBarStyleDefault;
}
@end
  • 在跳转到使用系统导航栏的页面(如系统相册、icloud drive)出现控制器内容上移被系统导航栏遮挡的问题时,请在跳转前设置
UIScrollView.appearance.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentAutomatic;
  • 【导航控制器为ZXNavigationBarNavigationController或其子类时,可忽略此步操作!!】ZXNavigationBarController作了自动隐藏导航栏的处理,但由于导航栏早于内部子控制器加载,因此有可能造成自定义导航栏抖动或状态栏颜色黑白相嵌的问题, 若您遇到此问题,请在base导航控制器的pushViewController:animated:中设置self.navigationBarHidden = YES;或在Appdelegate的application:didFinishLaunchingWithOptions:中调用方法[UINavigationController zx_hideAllNavBar](需要先#import "ZXNavigationBarController.h")
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //这个方法需要在导航控制器加载前调用
    [UINavigationController zx_hideAllNavBar];
    
    UIWindow *window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    DemoListViewController *vc = [[DemoListViewController alloc]init];
    UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:vc];
    window.rootViewController = nav;
    [window makeKeyAndVisible];
    self.window = window;
    return YES;
}
@end

【重要】如果您在项目中使用了FDFullscreenPopGesture

  • ZXNavigationBar支持全屏手势返回和拦截,建议您移除其他的第三方全屏手势返回框架以避免冲突。
  • 若自定义导航栏与系统导航栏同在一个项目中,您可以在继承于ZXNavigationBarController的跟控制器的初始化方法书写以下代码以兼容FDFullscreenPopGesture:
//因FDFullscreenPopGesture默认会在控制器即将展示时显示系统导航栏,与ZXNavigationBar共同使用时会造成系统导航栏出现一下又马上消失,因此需要以下设置
self.fd_prefersNavigationBarHidden = YES;
//当您通过zx_handlePopBlock拦截侧滑返回手势时,请设置fd_interactivePopDisabled为YES以关闭FDFullscreenPopGesture在当前控制器的全屏返回手势,否则无法拦截。
self.fd_interactivePopDisabled = YES;

【重要】ZXNavigationBar对于自定义导航栏view内容无法自动下移的处理方式

如果App使用的是系统的导航栏且不透明,view的内容会自动下移,例如非刘海屏会下移64像素;若设置了自定义的导航栏,因为它实际上就是普通的View,则控制器view中的内容不会自动下移以避免挡住导航栏。

  • ZXNavigationBar的处理方法是:
  • 如果您是通过frame或者Masonry设置控件布局,请设置y距离顶部高度为导航栏高度,可直接使用ZXNavBarHeight这个宏
  • 如果您是通过Xib加载控制器View,则ZXNavigationBar会自动将内部约束设置为距离顶部为导航栏高度+原始高度,您无需作任何处理

导航栏设置

注意:以下设置均在控制器中进行,self代表当前控制器(当前控制器需继承于ZXNavigationBarController)

设置导航栏标题

self.title = @"ZXNavigationBar";

self.zx_navTitle = @"ZXNavigationBar";

设置导航栏标题颜色

self.zx_navTitleColor = [UIColor redColor];

设置导航栏标题字体大小

self.zx_navTitleFontSize = 20;

self.zx_navTitleFont = [UIFont systemFontOfSize:20];
  • 设置导航栏标题其他非frame属性,通过控制self.zx_navTitleLabel即可

自定义导航栏frame

self.zx_navFixFrame = CGRectMake(0, 0, 100, 100);

导航栏frame发生改变时的回调,可在这个block中return修改后的frame

self.zx_navHandleFrameBlock = ^CGRect(CGRect oldFrame) {
    return CGRectMake(0, 0, 100, 100);
};

设置导航栏默认返回按钮图片,若不设置则使用默认的返回按钮图片

self.zx_backBtnImageName = @"newBackImageName";

快速设置左侧/右侧的按钮和点击回调(以最右侧按钮为例)

  • 设置最右侧按钮的图片名和点击回调
[self zx_setRightBtnWithImgName:@"set_icon" clickedBlock:^(UIButton * _Nonnull btn) {
    NSLog(@"点击了最右侧的Button");
}];
  • 设置最右侧按钮的文字和点击回调
[self zx_setRightBtnWithText:@"右侧按钮" clickedBlock:^(UIButton * _Nonnull btn) {
    NSLog(@"点击了最右侧的Button");
}];
  • 设置最右侧按钮的图片对象和点击回调
[self zx_setRightBtnWithImg:image对象 clickedBlock:^(ZXNavItemBtn * _Nonnull btn) {
    NSLog(@"点击了最右侧的Button");  
}];
  • 设置最右侧按钮的图片Url和点击回调(需导入SDWebImage并在pch文件中#import <SDWebImage/UIButton+WebCache.h>)
[self zx_setRightBtnWithImgUrl:@"图片url地址" placeholderImgName:@"占位图名称" clickedBlock:^(ZXNavItemBtn * _Nonnull btn) {
    NSLog(@"点击了最右侧的Button");  
}];

根据左侧/右侧的按钮对象进行具体设置(以左侧按钮为例)

  • 如果需要导航栏显示返回图标和返回文字
//由于ZXNavigationBar会自动在左侧添加返回图片和点击返回事件,因此只需要设置返回的文字即可
[self.zx_navLeftBtn setTitle:@"返回" forState:UIControlStateNormal];
  • 设置导航栏左侧/右侧的按钮的其他非frame相关属性,通过控制self.zx_navLeftBtn/zx_navRightBtn即可

将图片渲染为指定颜色

//将oldImage渲染为红色
UIImage *resultImage = [oldImage zx_renderingColor:[UIColor redColor]];

设置左侧/右侧的按钮的大小

//将按钮宽高设置为30
self.zx_navItemSize = 30;

设置左侧/右侧的按钮的间距与边距

//将按钮边距设置为0
self.zx_navItemMargin = 0;

设置右侧第二个按钮

  • 将上述例子中zx_navLeftBtn/zx_navRightBtn修改为zx_navSubRightBtn即可

设置左侧第二个按钮

  • 将上述例子中zx_navLeftBtn/zx_navRightBtn修改为zx_navSubLeftBtn即可

单独设置指定ZXNavItemBtn的属性(ZXNavItemBtn在导航栏中从左到右分别为zx_navLeftBtn,zx_navSubLeftBtn,zx_navSubRightBtn,zx_navRightBtn),以下以zx_navLeftBtn为例:

  • 设置NavItemBtn的image颜色
self.zx_navLeftBtn.zx_imageColor = [UIColor redColor];
  • 设置NavItemBtn的tintColor
self.zx_navLeftBtn.zx_tintColor = [UIColor redColor];
  • 设置NavItemBtn的字体大小
self.zx_navLeftBtn.zx_fontSize = 12;
  • 设置NavItemBtn的固定宽度,若设置,则ZXNavDefalutItemSize无效,若要恢复初始值,可设置为-1
self.zx_navLeftBtn.zx_fixWidth = 100;
  • 设置NavItemBtn的固定高度,若设置,则自动计算宽度无效(若需要恢复自动宽度,可设置zx_fixWidth为-1)
self.zx_navLeftBtn.zx_fixHeight = 100;
  • 设置NavItemBtn距离左边元素的固定距离,若要恢复初始值,可设置为-1
self.zx_navLeftBtn.zx_fixMarginLeft = 15;
  • 设置NavItemBtn距离右边元素的固定距离,若要恢复初始值,可设置为-1
self.zx_navLeftBtn.zx_fixMarginRight = 15;
  • 禁止自动调整NavItemBtn图片和文字的布局,若要使contentEdgeInsets、titleEdgeInsets、imageEdgeInsets等,则需要将此属性设置为NO
self.zx_navLeftBtn.zx_disableAutoLayoutImageAndTitle = YES;
  • 设置NavItemBtn image的固定大小
self.zx_navLeftBtn.zx_fixImageSize = CGSizeMake(10,10);
  • 设置NavItemBtn自动计算宽度后的附加宽度
self.zx_navLeftBtn.zx_textAttachWidth = 20;
  • 设置NavItemBtn文字的附加高度
self.zx_navLeftBtn.zx_textAttachHeight = 10;
  • 设置NavItemBtn的cornerRadius为高度的一半(圆形圆角)
self.zx_navLeftBtn.zx_setCornerRadiusRounded = YES;
  • 设置NavItemBtn内部图片x轴的偏移量,负数代表左移,无title且设置了zx_fixImageSize后生效,仅改变内容imageView的位移,不会改变原始NavItemBtn的frame
self.zx_navLeftBtn.zx_imageOffsetX = -10;
  • 设置NavItemBtn的tintColor仅用于UIControlStateNormal状态(请在zx_imageColor和zx_tintColor之前设置),默认为NO
self.zx_navLeftBtn.zx_useTintColorOnlyInStateNormal = YES;
  • 自定义NavItemView
self.zx_navLeftBtn.zx_customView = [UISwitch new];
  • 设置NavItemBtn frame发生改变时的回调,可在这个block中return修改后的frame
self.zx_navLeftBtn.zx_handleFrameBlock = ^CGRect(CGRect oldFrame) {
    return CGRectMake(oldFrame.origin.x, oldFrame.origin.y, oldFrame.size.width + 10, 30);
};

设置导航栏背景颜色

self.zx_navBarBackgroundColor = [UIColor orangeColor];

设置导航栏背景图片

self.zx_navBarBackgroundImage = [UIImage imageNamed:@"nav_bac"];

设置导航栏渐变背景

//从magentaColor到cyanColor渐变
[self zx_setNavGradientBacFrom:[UIColor magentaColor] to:[UIColor cyanColor]];

移除导航栏渐变背景

[self zx_removeNavGradientBac];

设置导航栏TintColor(此属性可以将导航栏的title颜色、左右Button的文字和图片颜色修改为TintColor)

self.zx_navTintColor = [UIColor yellowColor];

自定义导航栏高度(若设置此属性,ZXNavigationBar将不再使用默认的导航栏高度)

self.zx_navFixHeight = 30;

设置导航栏大小标题效果

[self zx_setMultiTitle:@"ZXNavigationBar" subTitle:@"subTitle"];

[self zx_setMultiTitle:@"ZXNavigationBar" subTitle:@"subTitle" subTitleFont:[UIFont systemFontOfSize:10] subTitleTextColor:[UIColor redColor]];

设置分割线背景颜色

self.zx_navLineViewBackgroundColor = [UIColor blueColor];

设置分割线的高度,默认为1

self.zx_navLineViewHeight = 2;
  • 分割线其他其他非frame相关属性通过self.zx_navLineView设置即可

设置状态栏为白色

self.zx_navStatusBarStyle = ZXNavStatusBarStyleLight;

设置状态栏为黑色

self.zx_navStatusBarStyle = ZXNavStatusBarStyleDefault;

是否禁止根据zx_navStatusBarStyle自动调整状态栏颜色,默认为否

self.zx_disableAutoSetStatusBarStyle = YES;

显示系统导航栏(默认为否)

//显示系统导航栏将会自动隐藏ZXNavigationBar
self.zx_showSystemNavBar = YES;

隐藏ZXNavigationBar(默认为否)

self.zx_hideBaseNavBar = YES;

自定义导航栏与系统导航栏平滑过渡

//务必仅当存在系统导航栏与自定义导航栏过渡时启用,非必要请勿启用,否则可能造成自定义导航栏跳动,若当前控制器显示了系统导航栏,请于当前控制器pop的上一个控制器中使用self.zx_navEnableSmoothFromSystemNavBar = YES)
self.zx_navEnableSmoothFromSystemNavBar = YES;
  • 若需要更优的平滑过渡效果,请将您的导航控制器继承于ZXNavigationBarNavigationController或使用ZXNavigationBarNavigationController作为您的导航控制器

禁止Xib加载控制器情况下自动将顶部View约束下移导航栏高度(默认为否)

self.zx_disableNavAutoSafeLayout = YES;

Xib加载控制器情况下将所有约束为top且secondItem为控制器view或safeArea的子view约束constant设置为原始长度+导航栏高度,默认为NO(仅第一个),若设置为YES,将会遍历控制器view中的所有约束,对性能有一点影响(需要设置在[super viewDidLoad]之前)

self.zx_enableAdjustNavContainerAll = YES;

自动将顶部View约束下移导航栏高度时的回调,可拦截并自定义下移距离(从xib加载控制器view时生效)

//oldNavOffset:视图在xib中所设置的约束与顶部距离
//currentNavOffset:即将设置的视图与顶部的距离
//返回值为当前需要自定义设置的视图与控制器顶部的距离
self.zx_handleAdjustNavContainerOffsetBlock = ^CGFloat(CGFloat oldNavOffset, CGFloat currentNavOffset) {
    //此设置代表从xib加载控制器view时,控制器view中的内容距离控制器顶部10像素(默认距离顶部为导航栏高度)
    return 10;
};

自动显示导航栏历史堆栈,默认为NO

self.zx_showNavHistoryStackContentView = YES;

设置导航栏历史堆栈视图偏离的x值,默认为0(导航栏历史堆栈视图与屏幕左侧距离默认等于leftBtn与屏幕左侧距离,此属性用于自定义在此基础上增加或减少的水平位移)

self.zx_navHistoryStackContentViewOffsetX = 10;

设置导航栏历史堆栈视图Item展示最多的数量,默认为6个,超过6个显示由栈顶往下的6个

self.zx_navHistoryStackContentViewItemMaxLength = 10;

设置导航栏历史堆栈视图显示样式,默认为ZXNavHistoryStackViewStyleLight

self.zx_navHistoryStackViewStyle = ZXNavHistoryStackViewStyleDark;

自定义NavItemView

//以zx_navLeftBtn为例
self.zx_navLeftBtn.zx_customView = [UISwitch new];

自定义TitleView(建议自定义TitleView中的子控件与底部距离固定不变,以适配不同高度的导航栏)

//创建自定义View
UIView *customTitleView = [[UIView alloc]init];
[self zx_addCustomTitleView:customTitleView];

自定义导航栏View(建议导航栏View中的子控件与底部距离固定不变,以适配不同高度的导航栏)

//创建自定义View
UIView *customNav = [[UIView alloc]init];
[self zx_addCustomNavBar:customNav];

拦截侧滑返回手势和返回按钮点击事件

//拦截侧滑返回手势和返回按钮点击事件
self.zx_handlePopBlock = ^BOOL(ZXNavigationBarController * _Nonnull viewController, ZXNavPopBlockFrom popBlockFrom) {
    //viewController:当前控制器
    //popBlockFrom:通过什么方式(点击返回按钮或侧滑返回手势)触发pop操作
    
    //doSomething
    //返回YES则代表不禁止pop操作,返回NO则禁止pop操作
    return YES;
};

//如果您在项目中使用了FDFullscreenPopGesture,需要关闭FDFullscreenPopGesture在当前控制器的全屏侧滑返回手势,否则zx_handlePopBlock无法拦截侧滑返回手势
self.fd_interactivePopDisabled = YES;
  • 如果需要拦截的控制器未继承于ZXNavigationBarController,可以在继承于ZXNavigationBarNavigationController的自定义导航控制器的viewDidLoad中:
self.zx_navHandlePopGestureBlock = ^BOOL(UIViewController * _Nonnull topViewController) {
    //这里的优先级高于控制器中的self.zx_handlePopBlock。如果返回NO,则代表直接关闭侧滑返回手势,控制器中的self.zx_handlePopBlock不会触发;如果返回YES,则交由控制器处理
    return NO;
};

设置全屏返回手势

将您的导航控制器继承于`ZXNavigationBarNavigationController`或使用`ZXNavigationBarNavigationController`作为您的导航控制器即可

设置全屏返回手势响应范围

将您的导航控制器继承于ZXNavigationBarNavigationController或使用ZXNavigationBarNavigationController作为您的导航控制器
注意:因设置全屏返回手势响应范围禁用全屏pop手势属于同一导航控制器,为避免此属性被其他子控制器修改,以下代码建议写在子控制器的-viewWillAppear-viewDidAppear

//在控制器中:
//pop手势的触发范围比例,0-1,默认为1,即代表全屏触发
self.zx_popGestureCoverRatio = 0.5;

禁用全屏pop手势,若禁用,则pop触发范围为屏幕宽度的十分之一

//在控制器中:
self.zx_disableFullScreenGesture = YES;

监听全屏返回手势进度

将您的导航控制器继承于ZXNavigationBarNavigationController或使用ZXNavigationBarNavigationController作为您的导航控制器
注意:因手势进度监听的block属于同一导航控制器,为避免block被子控制器覆盖后失效,以下代码建议写在子控制器的-viewWillAppear-viewDidAppear

//在控制器中:
self.zx_handleCustomPopGesture = ^(CGFloat popOffsetProgress) {
    NSLog(@"popOffsetProgress--%lf",popOffsetProgress);
};

push自动隐藏tabbar

将您的导航控制器继承于ZXNavigationBarNavigationController或使用ZXNavigationBarNavigationController作为您的导航控制器即可 若您要禁用这一功能

//在控制器中:
self.navigationController.zx_disableAutoHidesBottomBarWhenPushed = YES;

兼容pop返回手势与scrollView横向滚动手势

注意:因判断是否支持多层级的手势同时触发的block属于同一导航控制器,为避免block被子控制器覆盖后失效,以下代码建议写在子控制器的-viewWillAppear-viewDidAppear

//在控制器中:
[self zx_setPopGestureCompatibleScrollView:self.scrollView];

兼容pop返回手势与scrollView横向滚动手势(自定义处理)

当导航控制器为ZXNavigationBarNavigationController或继承于ZXNavigationBarNavigationController时,如果需要更复杂的定制化的情况,可以使用下方的方式,以下代码的作用是在scrollView滚动到第一页的时候,支持pop手势多层级同时触发,为了更好的展示效果,建议关闭scrollView的bounces。此段代码与上方效果一致
注意:因判断是否支持多层级的手势同时触发的block属于同一导航控制器,为避免block被子控制器覆盖后失效,以下代码建议写在子控制器的-viewWillAppear-viewDidAppear

//在控制器中:
self.scrollView.bounces = NO;
__weak typeof(self) weakSelf = self;
self.zx_popGestureShouldRecognizeSimultaneously = ^BOOL(UIGestureRecognizer * _Nonnull otherGestureRecognizer) {
    if(weakSelf.scrollView.contentOffset.x < weakSelf.scrollView.width){
        return YES;
    }
    return NO;
};

设置伸缩式导航栏

  • 如果设置了控制器的Xib且在Xib中设置了子视图的约束(仅需设置展开或者折叠导航栏与动画效果速度,无需手动调整控制器View子视图的frame)
//第一个参数folded:控制是展开还是折叠导航栏;第二个参数speed:控制展开或收缩导航栏的速度,0-6,建议值为3;第三个参数offsetBlock:折叠动画导航栏位移回调;第四个参数completionBlock:折叠动画结束回调
[self zx_setNavFolded:YES speed:3 foldingOffsetBlock:nil foldCompletionBlock:nil];
  • 如果是通过Frame设置控制器View的子视图(如TableView),需要在foldingOffsetBlock回调中控制导航栏下方View的frame,使其始终紧贴导航栏底部
__weak typeof(self) weakSelf = self;
[self zx_setNavFolded:shouldFold speed:3 foldingOffsetBlock:^(CGFloat offset) {
    //tableView的y值跟随这导航栏变化(导航栏高度减小,tableView的y值减小)
    weakSelf.tableView.y += offset;
    //tableView的高度值跟随这导航栏变化(导航栏高度减小,tableView高度增加)
    weakSelf.tableView.height -= offset;
} 

通过ScrollView滚动自动控制导航栏透明效果(仿微博热搜效果)

  • 在控制器加载的时候,需要先设置导航栏透明(注意,不要直接设置导航栏的alpha或设置导航栏的背景色为[UIColor clearColor]),请使用:
//这一行代码实际上是把导航栏背景色的透明度改为0,仅改变RGBA中A(alpha)的值,如果导航栏有自定义背景色,则会从透明-自定义背景色过渡
self.zx_navBarBackgroundColorAlpha = 0;
  • 在scrollViewDidScroll中
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    //scrollView:滚动控制的scrollView,tableView或collectionView
    //fullChangeHeight:scrollView.contentOffset.y达到fullChangeHeight时,导航栏变为完全不透明
    //changeLimitNavAlphe:当导航栏透明度达到changeLimitNavAlphe时,将触发opaqueBlock,通知控制器设置导航栏不透明时的效果
    //transparentBlock:导航栏切换到透明状态时的回调(默认透明度0.7为临界点)
    //opaqueBlock:导航栏切换到不透明状态时的回调(默认透明度0.7为临界点)
    [self zx_setNavTransparentGradientsWithScrollView:scrollView fullChangeHeight:100 changeLimitNavAlphe:0.7 transparentGradientsTransparentBlock:^{
        //导航栏透明时的额外效果设置
    } transparentGradientsOpaqueBlock:^{
        //导航栏不透明时的额外效果设置
    }];
}
  • 若需要复杂的自定义场景(例如导航栏有背景图片,因默认处理方式是通过控制导航栏背景颜色的透明度实现,因此此时需要监听导航栏透明度改变回调,并写上self.zx_navBacImageView.alpha = alpha;
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    //scrollView:滚动控制的scrollView,tableView或collectionView
    //fullChangeHeight:scrollView.contentOffset.y达到fullChangeHeight时,导航栏变为完全不透明
    //changeLimitNavAlphe:当导航栏透明度达到changeLimitNavAlphe时,将触发opaqueBlock,通知控制器设置导航栏不透明时的效果
    //changingBlock:导航栏透明度正在改变时的回调
    //transparentBlock:导航栏切换到透明状态时的回调(默认透明度0.7为临界点)
    //opaqueBlock:导航栏切换到不透明状态时的回调(默认透明度0.7为临界点)
    [self zx_setNavTransparentGradientsWithScrollView:scrollView fullChangeHeight:100 changeLimitNavAlphe:0.7 transparentGradientsChangingBlock:^(CGFloat alpha) {
        //导航栏透明度正在改变时候处理
    } transparentGradientsTransparentBlock:^{
        //导航栏透明时的额外效果设置
    } transparentGradientsOpaqueBlock:^{
        //导航栏不透明时的额外效果设置
    }];
}

版本记录,请查阅Release


更多示例,可下载Demo查阅,若有任何问题,可随时在issue中提出

zxnavigationbar's People

Contributors

smilezxlee avatar vent-frais avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

zxnavigationbar's Issues

有没有白名单功能

想加白名单直接过滤掉不用的vc,要是能做到直接前缀就更好,旧项目用到了云信的uikit的框架,里面有不少vc又不想改源码,作者大大有没有简单的方法

判断刘海屏的方式有问题,导致在 iphone 11 pro max上获取到的状态栏高度是20,进而导致标题偏上

image
好像是这个刘海屏的判断有问题
/**
判断是否是刘海屏

@return 是否是刘海屏
*/
#define ZXIsBangScreen ({
int cFlag = 0;
if (@available(iOS 11.0, *)) {
if ([UIApplication sharedApplication].delegate.window.safeAreaInsets.top == 44) {
cFlag = 1;
}else{
cFlag = 0;
}
}else{
cFlag = 0;
}
cFlag;
})
我测试的手机是iphone 11 pro max 你这个宏定义获取到的状态栏高度是20,实际高度应该是44

我想在当前页面禁止pop手势,或者是拦截返回手势,设置以下无效,

请问具体需要怎么操作.谢谢.

  • (void)viewWillAppear:(BOOL)animated {
    self.zx_popGestureCoverRatio = 0.1;
    self.zx_handlePopBlock = ^BOOL(ZXNavigationBarController * _Nonnull viewController, ZXNavPopBlockFrom popBlockFrom) {
    //viewController:当前控制器
    //popBlockFrom:通过什么方式(点击返回按钮或侧滑返回手势)触发pop操作

      //doSomething
      //返回YES则代表不禁止pop操作,返回NO则禁止pop操作
      NSLog(@"");
      return NO;
    

    };
    }

如果将ZXNavigationBar的导航栏隐藏了是不是就不能监听返回手势了

在控制器里面加了self.zx_hideBaseNavBar = YES;
那么下面的拦截侧滑返回的手势就失效了吗?
//拦截侧滑返回手势和返回按钮点击事件
self.zx_handlePopBlock = ^BOOL(ZXNavigationBarController * _Nonnull viewController, ZXNavPopBlockFrom popBlockFrom) {
//viewController:当前控制器
//popBlockFrom:通过什么方式(点击返回按钮或侧滑返回手势)触发pop操作

    //doSomething
    //返回YES则代表不禁止pop操作,返回NO则禁止pop操作
    @strongify(self);
    [self backClick];
    
    return NO;
};

与masonry布局冲突

我baseController继承ZXNavigationBarController
然后隐藏导航栏

  • (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    self.zx_hideBaseNavBar = YES;
    }

  • (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    self.zx_hideBaseNavBar = NO;
    }

masonry布局为
[self.view addSubview:self.tableView];

[_tableView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.mas_equalTo(UIEdgeInsetsMake(kNavStatusBar, 0, kTabBarHeight, 0));
}];

其中kNavStatusBar打印为44 但是运行结果tableView.top 为0

TableViewController的显示有问题。

我看到你有设置ZXNavigationBarTableViewController,继承了之后,tableview的表头会计算成没有导航栏,会在 ZXNavigationBar的下面。

iPad竖屏下上面导航条高度为50

我去,我一直以为iPad上面也是44的高度呢,它竟然是50。。
完犊子了,那我之前的项目岂不是也要炸锅....
大佬,能不能考虑一下iPad上的适配啊,[拜托了],我先去做适配去了

BackButtonHandlerProtocol 协议名重复

BackButtonHandlerProtocol 这个协议,和老项目里有uiviewcontroller的分类的协议名字一样,导致项目报错无法运行,我可以给老项目的协议名更改吗? 改了会有影响吗? 你这在pod 没法改,加个前缀.

右按钮位置不对

在iOS10.3的系统上,右按钮大概率位置不对,但是在设置完右按钮文字或图片后,再次设置zx_navItemMargin, 这个问题得以解决。在iOS高版本上没发现有这个问题。

关于iPhone 12 mini NavigationBar 总高度问题

目前使用的是xcode12.2 iPhone 12 mini 模拟器出现的情况
按照以往常规的计算就是用状态栏高度加上NavigationBar固定44的高度来获取上面总的高度
示例代码
STATUSBAR_HEIGHT = [UIApplication sharedApplication].statusBarFrame.size.height
NAVBAR_HEIGHT = 44.0f
STATUSBAR_NAVBAR_HEIGHT = STATUSBAR_HEIGHT + NAVBAR_HEIGHT;
经过测试除了iPhone 12 mini 模拟器的高度有问题,其他的设备正常
目前iPhone 12 mini通过代码计算获取是88的高度,但是我随便新建一个项目工程打印总高度是94,也不知道是不是模拟器bug,因为没有真机暂时无法定位具体问题
这里提供截图和打印信息
CC552D75-4277-4B44-812A-4D472B8E5AD1

好像对TableViewController失效了

我新建项目用ZXNavigationBarTableViewController 设置TableViewController无效了。上方导航栏是空白的。普通的ViewController是正常的,而且我打开之前的项目,是正常的。新建项目的代码和用法完全复制之前项目的,只是xcode升级了,不知道你这个版本的代码测试过没有

safeArea布局问题

使用storyboard时,如果勾掉Use Safe Area Layout Guides时,tableView会距导航有64的间隔
如图所示
Simulator Screen Shot - iPhone 12 Pro Max - 2021-05-10 at 10 19 19

TableViewController还是有比较严重的问题

基本情况:静态表格,设置个tableHeaderView,在单元格中放置一个或几个textView。当textView输入文字产生换行时,顶部导航栏高度计算就会出问题,会延伸覆盖tableHeaderView。是在storyboard中设置的。应该区别不大。

提个建议

#pragma mark - 重写父类pop和push相关方法

  • (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
    self.navigationBarHidden = YES;
    [self updateTopViewController:viewController];
    if(!self.zx_disableAutoHidesBottomBarWhenPushed){
    [viewController setHidesBottomBarWhenPushed:self.viewControllers.count >= 1];
    }
    [super pushViewController:viewController animated:YES];
    }

改为

[super pushViewController:viewController animated:animated];

项目中用到,有时候真的不需要动画....

合qq的QMUIKit共同使用出现一个bug

我也不清楚是什么原因!就是我使用ZXNavigationBarNavigationController作为导航控制器的时候,侧滑的时候可以复现。
image
在这个地方开始多次循环然后野指针了。
QMUIKit里面的UIView+QMUI这个分类里面
image
我搞不清楚是什么问题了,大佬能不能帮忙看一下。
DEMO中pod导入 pod 'QMUIKit',侧滑即可复现。

手势侧滑返回

手势侧滑慢慢向右滑动,等滑动到最右边的时候 会出现系统导航栏突然闪烁一下

设置返回按钮默认图片

将HEBaseViewController 继承ZXNavigationBarController,我再基类里定义返回按钮图片, self.zx_backBtnImageName = @"back_black",所有的顶层ViewController都会显示返回按钮。

设置返回按钮默认图片应该也需要加入这个判断 if(self.navigationController && self.navigationController.viewControllers.count > 1)

有两处代码写错了

位置:ZXNavigationBarController.m
行数:510行和521行
描述:给leftButton和rightButton添加的点击回调赋值给了subRightButton

#pragma mark 设置左侧按钮图片和点击回调
- (void)zx_setLeftBtnWithImg:(UIImage *)img clickedBlock:(nullable leftBtnClickedBlock)clickBlock{
    [self.zx_navLeftBtn setImage:img forState:UIControlStateNormal];
    ((ZXNavigationBar *)self.zx_navBar).zx_subRightBtnClickedBlock = ^(ZXNavItemBtn * _Nonnull btn) {
        if(clickBlock){
            clickBlock(btn);
        }
    };
    
}

#pragma mark 设置右侧按钮图片和点击回调
- (void)zx_setRightBtnWithImg:(UIImage *)img clickedBlock:(nullable leftBtnClickedBlock)clickBlock{
    [self.zx_navRightBtn setImage:img forState:UIControlStateNormal];
    ((ZXNavigationBar *)self.zx_navBzx_subRightBtnClickedBlockck** = ^(ZXNavItemBtn * _Nonnull btn) {
        if(clickBlock){
            clickBlock(btn);
        }
    };
    
}

设置多个ScrollView手势冲突,只有最后一个才会支持手势返回

如果一个ViewController里, 有一个横向移动的UICollectionView, 还有一个UIScrollview分页控制器的话.
如下设置,
[self zx_setPopGestureCompatibleScrollView:self.horizontalView.collectionView];
[self zx_setPopGestureCompatibleScrollView:self.scrollView];
或者
[self zx_setPopGestureCompatibleScrollViews:@[self.horizontalView.collectionView, self.scrollView]];

这样设置的话, 只有最后一个设置手势冲突的UIView,才会支持手势返回.

代码建议

UIView+ZXNavFrameExtension这个分类里面的方法建议加上前缀zx_

直接设置导航栏透明效果

我看到只有跟随ScrollView设置导航栏透明度效果,我尝试自定义导航栏透明无效,有什么方法能直接设置导航栏透明吗?

当导航条透明时跳转到使用系统导航条的页面,返回的时候顶部透明效果需要优化

hello,大佬,我又来了!来一波py交易
需要优化的样式:
IMG_889A59961173-1
复现方法:
在微博demoDemoWeiboHotViewController中 设置右上角按钮点击跳转到使用系统导航条的页面

    [self zx_setRightBtnWithImgName:@"right_more_icon" clickedBlock:^(ZXNavItemBtn * _Nonnull btn) {
        NSLog(@"点击了最右边的按钮");
        Class DemoSystemBarViewController = NSClassFromString(@"DemoSystemBarViewController");
        id vc = [DemoSystemBarViewController new];
        [self.navigationController pushViewController:vc animated:YES];
    }];

看看能不能优化一波。

返回按钮

用系统的导航栏push继承ZXNavigationBar导航的页面 如何去掉系统返回的字段
WeChat0bfcae1116e78a19c2ebd70b85cb30a0在视图层看到的效果是这样的WeChatee10ac1d3e869a923fce888f41ab2508最上方有一个导航

关于tableViewController

如何支持tableViewController呢? 一些页面想在storyBoard上直接用TableViewController的静态cell画UI,没办法继承作者的ZXNavigationBarController,能否扩展一下?

可以适配RTL吗

因为项目要适配阿拉伯语言,全都是镜像,页面都是反的

暗黑模式

我看标题是可以正常响应的,但是leftBtn和rightBtn会很奇怪,有的时候能响应,有的时候不能响应。

push到B页面,B页面有个分页控制器,在分页控制器里面的第一页里面不能响应全屏返回手势

//加这一行代码即可解决ScrollView与侧滑返回手势冲突问题
//[self zx_setPopGestureCompatibleScrollView:self.pageController.downSc];
__weak typeof(self) weakSelf = self;
self.zx_popGestureShouldRecognizeSimultaneously = ^BOOL(UIGestureRecognizer * _Nonnull otherGestureRecognizer) {
if(weakSelf.pageController.downSc.contentOffset.x <= 0){
return YES;
}
return NO;
};
这个代码加了没效果。

设置状态栏颜色不管事怎么解决

self.zx_navStatusBarStyle = ZXNavStatusBarStyleLight; 在当前控制器,不管事,怎么解决???

-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
下边这种方法也不管事,还是黑色的,不知道为什么?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.