├── .gitignore ├── .gitattributes ├── ZXNavigationBarDemo ├── ZXNavigationBarDemo │ ├── Assets.xcassets │ │ ├── Contents.json │ │ ├── nav_bac.imageset │ │ │ ├── nav_bac.png │ │ │ └── Contents.json │ │ ├── set_icon.imageset │ │ │ ├── set_icon2.png │ │ │ └── Contents.json │ │ ├── light_icon.imageset │ │ │ ├── light_icon.png │ │ │ └── Contents.json │ │ ├── search_icon.imageset │ │ │ ├── search_icon.png │ │ │ └── Contents.json │ │ ├── recycle_icon.imageset │ │ │ ├── recycle_icon.png │ │ │ └── Contents.json │ │ ├── weibo_hot_bac.imageset │ │ │ ├── weibo_hot_bac.jpg │ │ │ └── Contents.json │ │ ├── right_more_icon.imageset │ │ │ ├── right_more_icon.png │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── ZXNavigationBar │ │ ├── ZXNavigationBar.bundle │ │ │ └── back_icon.png │ │ ├── ZXNavigationBarSubViews │ │ │ ├── ZXNavBacImageView.m │ │ │ ├── ZXNavHistoryStackView │ │ │ │ ├── Model │ │ │ │ │ ├── ZXNavHistoryStackModel.m │ │ │ │ │ └── ZXNavHistoryStackModel.h │ │ │ │ └── View │ │ │ │ │ ├── ZXNavHistoryStackView.h │ │ │ │ │ ├── ZXNavHistoryStackCell.h │ │ │ │ │ ├── ZXNavHistoryStackView.m │ │ │ │ │ ├── ZXNavHistoryStackContentView.h │ │ │ │ │ ├── ZXNavHistoryStackCell.m │ │ │ │ │ └── ZXNavHistoryStackContentView.m │ │ │ ├── ZXNavTitleView.h │ │ │ ├── ZXNavBacImageView.h │ │ │ ├── ZXNavTitleLabel.h │ │ │ ├── ZXNavTitleView.m │ │ │ ├── ZXNavTitleLabel.m │ │ │ └── ZXNavItemBtn.h │ │ ├── ZXNavigationBarHelper │ │ │ └── ZXNavigationBarCategory │ │ │ │ ├── UIImage+ZXNavBundleExtension.h │ │ │ │ ├── UIImage+ZXNavColorRender.h │ │ │ │ ├── NSString+ZXNavCalcSizeExtension.h │ │ │ │ ├── NSAttributedString+ZXNavCalcSizeExtension.h │ │ │ │ ├── ZXNavigationBarController+ZXNavSystemBarPopHandle.h │ │ │ │ ├── UINavigationController+ZXNavBarAllHiddenExtension.h │ │ │ │ ├── UIView+ZXNavFrameExtension.h │ │ │ │ ├── UIImage+ZXNavBundleExtension.m │ │ │ │ ├── NSAttributedString+ZXNavCalcSizeExtension.m │ │ │ │ ├── UIImage+ZXNavColorRender.m │ │ │ │ ├── NSString+ZXNavCalcSizeExtension.m │ │ │ │ ├── UINavigationController+ZXNavBarAllHiddenExtension.m │ │ │ │ ├── ZXNavigationBarController+ZXNavSystemBarPopHandle.m │ │ │ │ └── UIView+ZXNavFrameExtension.m │ │ ├── ZXNavigationBarNavigationController.h │ │ ├── ZXNavigationBar.h │ │ ├── ZXNavigationBarDefine.h │ │ └── ZXNavigationBarNavigationController.m │ ├── AppDelegate.h │ ├── Demo │ │ ├── DemoCustomNavViewController │ │ │ ├── DemoCustomNav │ │ │ │ ├── DemoCustomNav.h │ │ │ │ ├── DemoCustomNav.m │ │ │ │ └── DemoCustomNav.xib │ │ │ ├── DemoCustomNavViewController.h │ │ │ └── DemoCustomNavViewController.m │ │ ├── DemoCustomTitleViewViewController │ │ │ ├── DemoCustomTitleView │ │ │ │ ├── DemoCustomTitleView.h │ │ │ │ ├── DemoCustomTitleView.m │ │ │ │ └── DemoCustomTitleView.xib │ │ │ ├── DemoCustomTitleViewViewController.h │ │ │ └── DemoCustomTitleViewViewController.m │ │ ├── DemoBaseViewController │ │ │ ├── DemoBaseViewController.h │ │ │ └── DemoBaseViewController.m │ │ ├── DemoListViewController │ │ │ ├── DemoListViewController.h │ │ │ └── DemoListViewController.m │ │ ├── DemoXibViewController │ │ │ ├── DemoXibViewController.h │ │ │ └── DemoXibViewController.m │ │ ├── DemoFoldXibViewController │ │ │ ├── DemoFoldXibViewController.h │ │ │ ├── DemoFoldXibViewController.xib │ │ │ └── DemoFoldXibViewController.m │ │ ├── DemoWeiboHotViewController │ │ │ ├── DemoWeiboHotViewController.h │ │ │ └── DemoWeiboHotViewController.m │ │ ├── DemoFoldFrameViewController │ │ │ ├── DemoFoldFrameViewController.h │ │ │ └── DemoFoldFrameViewController.m │ │ ├── DemoSystemBarViewController │ │ │ ├── DemoPublicSystemBarViewController.h │ │ │ ├── DemoSystemBarViewController.h │ │ │ ├── DemoSystemBarViewController.m │ │ │ └── DemoPublicSystemBarViewController.m │ │ └── DemoCompatibleScrollViewViewController │ │ │ ├── DemoCompatibleScrollViewViewController.h │ │ │ └── DemoCompatibleScrollViewViewController.m │ ├── main.m │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Info.plist │ └── AppDelegate.m ├── ZXNavigationBarDemo.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcuserdata │ │ │ ├── lzx.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ │ └── mac.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ ├── lzx.xcuserdatad │ │ ├── xcschemes │ │ │ └── xcschememanagement.plist │ │ └── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ │ └── mac.xcuserdatad │ │ ├── xcschemes │ │ └── xcschememanagement.plist │ │ └── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist └── ZXNavigationBarDemoUITests │ ├── Info.plist │ └── ZXNavigationBarDemoUITests.m ├── ZXNavigationBar ├── ZXNavigationBar.bundle │ └── back_icon.png ├── ZXNavigationBarSubViews │ ├── ZXNavBacImageView.m │ ├── ZXNavHistoryStackView │ │ ├── Model │ │ │ ├── ZXNavHistoryStackModel.m │ │ │ └── ZXNavHistoryStackModel.h │ │ └── View │ │ │ ├── ZXNavHistoryStackView.h │ │ │ ├── ZXNavHistoryStackCell.h │ │ │ ├── ZXNavHistoryStackView.m │ │ │ ├── ZXNavHistoryStackContentView.h │ │ │ ├── ZXNavHistoryStackCell.m │ │ │ └── ZXNavHistoryStackContentView.m │ ├── ZXNavTitleView.h │ ├── ZXNavBacImageView.h │ ├── ZXNavTitleLabel.h │ ├── ZXNavTitleView.m │ ├── ZXNavTitleLabel.m │ ├── ZXNavItemBtn.h │ └── ZXNavItemBtn.m ├── ZXNavigationBarHelper │ └── ZXNavigationBarCategory │ │ ├── UIImage+ZXNavBundleExtension.h │ │ ├── UIImage+ZXNavColorRender.h │ │ ├── NSString+ZXNavCalcSizeExtension.h │ │ ├── NSAttributedString+ZXNavCalcSizeExtension.h │ │ ├── ZXNavigationBarController+ZXNavSystemBarPopHandle.h │ │ ├── UINavigationController+ZXNavBarAllHiddenExtension.h │ │ ├── UIView+ZXNavFrameExtension.h │ │ ├── UIImage+ZXNavBundleExtension.m │ │ ├── NSAttributedString+ZXNavCalcSizeExtension.m │ │ ├── UIImage+ZXNavColorRender.m │ │ ├── NSString+ZXNavCalcSizeExtension.m │ │ ├── UINavigationController+ZXNavBarAllHiddenExtension.m │ │ ├── ZXNavigationBarController+ZXNavSystemBarPopHandle.m │ │ └── UIView+ZXNavFrameExtension.m ├── ZXNavigationBarNavigationController.h ├── ZXNavigationBar.h ├── ZXNavigationBarDefine.h └── ZXNavigationBarNavigationController.m ├── ZXNavigationBar.podspec └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | Thumbs.db 3 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBar.bundle/back_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileZXLee/ZXNavigationBar/HEAD/ZXNavigationBar/ZXNavigationBar.bundle/back_icon.png -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/nav_bac.imageset/nav_bac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileZXLee/ZXNavigationBar/HEAD/ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/nav_bac.imageset/nav_bac.png -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/set_icon.imageset/set_icon2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileZXLee/ZXNavigationBar/HEAD/ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/set_icon.imageset/set_icon2.png -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/light_icon.imageset/light_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileZXLee/ZXNavigationBar/HEAD/ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/light_icon.imageset/light_icon.png -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/search_icon.imageset/search_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileZXLee/ZXNavigationBar/HEAD/ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/search_icon.imageset/search_icon.png -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBar.bundle/back_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileZXLee/ZXNavigationBar/HEAD/ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBar.bundle/back_icon.png -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/recycle_icon.imageset/recycle_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileZXLee/ZXNavigationBar/HEAD/ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/recycle_icon.imageset/recycle_icon.png -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/weibo_hot_bac.imageset/weibo_hot_bac.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileZXLee/ZXNavigationBar/HEAD/ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/weibo_hot_bac.imageset/weibo_hot_bac.jpg -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/right_more_icon.imageset/right_more_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileZXLee/ZXNavigationBar/HEAD/ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/right_more_icon.imageset/right_more_icon.png -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo.xcodeproj/project.xcworkspace/xcuserdata/lzx.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileZXLee/ZXNavigationBar/HEAD/ZXNavigationBarDemo/ZXNavigationBarDemo.xcodeproj/project.xcworkspace/xcuserdata/lzx.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo.xcodeproj/project.xcworkspace/xcuserdata/mac.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SmileZXLee/ZXNavigationBar/HEAD/ZXNavigationBarDemo/ZXNavigationBarDemo.xcodeproj/project.xcworkspace/xcuserdata/mac.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavBacImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavBacImageView.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavBacImageView.h" 11 | 12 | @implementation ZXNavBacImageView 13 | 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCustomNavViewController/DemoCustomNav/DemoCustomNav.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCustomNav.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoCustomNav : UIView 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavBacImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavBacImageView.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavBacImageView.h" 11 | 12 | @implementation ZXNavBacImageView 13 | 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/Model/ZXNavHistoryStackModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackModel.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavHistoryStackModel.h" 11 | 12 | @implementation ZXNavHistoryStackModel 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavTitleView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavTitleView.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavTitleView : UIView 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavBacImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavBacImageView.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavBacImageView : UIImageView 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCustomTitleViewViewController/DemoCustomTitleView/DemoCustomTitleView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCustomTitleView.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoCustomTitleView : UIView 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoBaseViewController/DemoBaseViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoBaseViewController.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "ZXNavigationBarController.h" 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface DemoBaseViewController : ZXNavigationBarController 13 | 14 | @end 15 | 16 | NS_ASSUME_NONNULL_END 17 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoListViewController/DemoListViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoListViewController.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoBaseViewController.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoListViewController : DemoBaseViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoXibViewController/DemoXibViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoXibViewController.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoBaseViewController.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoXibViewController : ZXNavigationBarController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoFoldXibViewController/DemoFoldXibViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoFoldXibViewController.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/13. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoBaseViewController.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoFoldXibViewController : DemoBaseViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoWeiboHotViewController/DemoWeiboHotViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoWeiboHotViewController.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoBaseViewController.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoWeiboHotViewController : DemoBaseViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/Model/ZXNavHistoryStackModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackModel.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavHistoryStackModel.h" 11 | 12 | @implementation ZXNavHistoryStackModel 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/nav_bac.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "nav_bac.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCustomNavViewController/DemoCustomNavViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCustomNavViewController.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoBaseViewController.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoCustomNavViewController : DemoBaseViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoFoldFrameViewController/DemoFoldFrameViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoTelescopicViewController.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/13. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoBaseViewController.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoFoldFrameViewController : DemoBaseViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoSystemBarViewController/DemoPublicSystemBarViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoPublicSystemBarViewController.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/8/4. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoPublicSystemBarViewController : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavTitleView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavTitleView.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavTitleView : UIView 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/light_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "light_icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/set_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "set_icon2.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/recycle_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "recycle_icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/search_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "search_icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/weibo_hot_bac.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "weibo_hot_bac.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/right_more_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "right_more_icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavBacImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavBacImageView.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavBacImageView : UIImageView 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackView.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavHistoryStackView : UICollectionView 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCustomTitleViewViewController/DemoCustomTitleViewViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCustomTitleViewViewController.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoBaseViewController.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoCustomTitleViewViewController : DemoBaseViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoSystemBarViewController/DemoSystemBarViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoSystemBarViewController.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/11. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DemoBaseViewController.h" 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoSystemBarViewController : DemoBaseViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo.xcodeproj/xcuserdata/lzx.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ZXNavigationBarDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ZXNavigationBarDemo.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCompatibleScrollViewViewController/DemoCompatibleScrollViewViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCompatibleScrollViewViewController.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/7/29. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoBaseViewController.h" 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface DemoCompatibleScrollViewViewController : DemoBaseViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackView.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavHistoryStackView : UICollectionView 15 | 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIImage+ZXNavBundleExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ZXNavBundleExtension.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/11. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIImage (ZXNavBundleExtension) 15 | + (UIImage *)zx_imageFromBundleWithImageName:(NSString *)imageName; 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavTitleLabel.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavTitleLabel.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavTitleLabel : UILabel 15 | //NavTitleLabel的frame更新回调 16 | @property (copy, nonatomic) void (^zx_titleLabelFrameUpdateBlock)(ZXNavTitleLabel *titleLabel); 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ZXNavigationBar.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'ZXNavigationBar' 3 | s.version = '1.4.1' 4 | s.summary = '灵活轻量的自定义导航栏,轻松实现各种自定义效果' 5 | s.homepage = 'https://github.com/SmileZXLee/ZXNavigationBar' 6 | s.license = 'MIT' 7 | s.authors = {'李兆祥' => '393727164@qq.com'} 8 | s.platform = :ios, '8.0' 9 | s.source = {:git => 'https://github.com/SmileZXLee/ZXNavigationBar.git', :tag => s.version} 10 | s.source_files = 'ZXNavigationBar/**/*.{h,m}' 11 | s.resource = 'ZXNavigationBar/ZXNavigationBar.bundle' 12 | s.requires_arc = true 13 | end -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCustomNavViewController/DemoCustomNav/DemoCustomNav.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCustomNav.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoCustomNav.h" 10 | 11 | @implementation DemoCustomNav 12 | 13 | /* 14 | // Only override drawRect: if you perform custom drawing. 15 | // An empty implementation adversely affects performance during animation. 16 | - (void)drawRect:(CGRect)rect { 17 | // Drawing code 18 | } 19 | */ 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavTitleView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavTitleView.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavTitleView.h" 11 | 12 | @implementation ZXNavTitleView 13 | 14 | /* 15 | // Only override drawRect: if you perform custom drawing. 16 | // An empty implementation adversely affects performance during animation. 17 | - (void)drawRect:(CGRect)rect { 18 | // Drawing code 19 | } 20 | */ 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIImage+ZXNavBundleExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ZXNavBundleExtension.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/11. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIImage (ZXNavBundleExtension) 15 | + (UIImage *)zx_imageFromBundleWithImageName:(NSString *)imageName; 16 | @end 17 | 18 | NS_ASSUME_NONNULL_END 19 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavTitleLabel.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavTitleLabel.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavTitleLabel : UILabel 15 | //NavTitleLabel的frame更新回调 16 | @property (copy, nonatomic) void (^zx_titleLabelFrameUpdateBlock)(ZXNavTitleLabel *titleLabel); 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIImage+ZXNavColorRender.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ZXNavColorRender.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIImage (ZXNavColorRender) 15 | 16 | /** 17 | 图片渲染 18 | 19 | @param color 需要渲染的颜色 20 | @return 渲染后的图片 21 | */ 22 | - (UIImage *)zx_renderingColor:(UIColor *)color; 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavTitleView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavTitleView.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavTitleView.h" 11 | 12 | @implementation ZXNavTitleView 13 | 14 | /* 15 | // Only override drawRect: if you perform custom drawing. 16 | // An empty implementation adversely affects performance during animation. 17 | - (void)drawRect:(CGRect)rect { 18 | // Drawing code 19 | } 20 | */ 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIImage+ZXNavColorRender.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ZXNavColorRender.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIImage (ZXNavColorRender) 15 | 16 | /** 17 | 图片渲染 18 | 19 | @param color 需要渲染的颜色 20 | @return 渲染后的图片 21 | */ 22 | - (UIImage *)zx_renderingColor:(UIColor *)color; 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackCell.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import "ZXNavHistoryStackModel.h" 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavHistoryStackCell : UICollectionViewCell 15 | @property (strong, nonatomic) ZXNavHistoryStackModel *historyStackModel; 16 | @property (assign, nonatomic) ZXNavHistoryStackViewStyle historyStackViewStyle; 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/NSString+ZXNavCalcSizeExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+ZXNavCalcSizeExtension.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface NSString (ZXNavCalcSizeExtension) 15 | - (CGFloat)zx_getRectHeightWithLimitW:(CGFloat)limitW fontSize:(CGFloat)fontSize; 16 | - (CGFloat)zx_getRectWidthWithLimitH:(CGFloat)limitH fontSize:(CGFloat)fontSize; 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoBaseViewController/DemoBaseViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoBaseViewController.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoBaseViewController.h" 10 | 11 | @interface DemoBaseViewController () 12 | 13 | @end 14 | 15 | @implementation DemoBaseViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | self.zx_navStatusBarStyle = ZXNavStatusBarStyleDefault; 20 | self.zx_showNavHistoryStackContentView = YES; 21 | } 22 | 23 | - (void)dealloc{ 24 | NSLog(@"%@-dealloc",[self class]); 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCustomTitleViewViewController/DemoCustomTitleView/DemoCustomTitleView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCustomTitleView.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoCustomTitleView.h" 10 | @interface DemoCustomTitleView() 11 | @property (weak, nonatomic) IBOutlet UIView *titleView; 12 | 13 | @end 14 | @implementation DemoCustomTitleView 15 | 16 | - (void)layoutSubviews{ 17 | [super layoutSubviews]; 18 | self.titleView.layer.cornerRadius = self.titleView.frame.size.height / 2; 19 | self.titleView.clipsToBounds = YES; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackCell.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import "ZXNavHistoryStackModel.h" 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavHistoryStackCell : UICollectionViewCell 15 | @property (strong, nonatomic) ZXNavHistoryStackModel *historyStackModel; 16 | @property (assign, nonatomic) ZXNavHistoryStackViewStyle historyStackViewStyle; 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/NSString+ZXNavCalcSizeExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+ZXNavCalcSizeExtension.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface NSString (ZXNavCalcSizeExtension) 15 | - (CGFloat)zx_getRectHeightWithLimitW:(CGFloat)limitW fontSize:(CGFloat)fontSize; 16 | - (CGFloat)zx_getRectWidthWithLimitH:(CGFloat)limitH fontSize:(CGFloat)fontSize; 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/NSAttributedString+ZXNavCalcSizeExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+ZXNavCalcSizeExtension.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/10/23. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface NSAttributedString (ZXNavCalcSizeExtension) 15 | - (CGFloat)zx_getAttrRectWidthWithLimitH:(CGFloat)limitH fontSize:(CGFloat)fontSize; 16 | - (CGFloat)zx_getAttrRectHeightWithLimitW:(CGFloat)limitW fontSize:(CGFloat)fontSize; 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackView.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavHistoryStackView.h" 11 | 12 | @implementation ZXNavHistoryStackView 13 | 14 | #pragma mark - Init 15 | - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(nonnull UICollectionViewLayout *)layout{ 16 | self = [super initWithFrame:frame collectionViewLayout:layout]; 17 | if(self){ 18 | [self setUp]; 19 | } 20 | return self; 21 | } 22 | 23 | - (void)setUp{ 24 | 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/NSAttributedString+ZXNavCalcSizeExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+ZXNavCalcSizeExtension.h 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/10/23. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface NSAttributedString (ZXNavCalcSizeExtension) 15 | - (CGFloat)zx_getAttrRectWidthWithLimitH:(CGFloat)limitH fontSize:(CGFloat)fontSize; 16 | - (CGFloat)zx_getAttrRectHeightWithLimitW:(CGFloat)limitW fontSize:(CGFloat)fontSize; 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/ZXNavigationBarController+ZXNavSystemBarPopHandle.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBarController+ZXNavSystemBarPopHandle.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/5/29. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | //Thanks to @onegray https://github.com/onegray/UIViewController-BackButtonHandler Respect! 11 | 12 | #import "ZXNavigationBarController.h" 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | @protocol ZXBackButtonHandlerProtocol 16 | @optional 17 | 18 | -(BOOL)zx_navSystemBarPopHandle; 19 | @end 20 | @interface UIViewController (ZXNavSystemBarPopHandle) 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackView.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavHistoryStackView.h" 11 | 12 | @implementation ZXNavHistoryStackView 13 | 14 | #pragma mark - Init 15 | - (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(nonnull UICollectionViewLayout *)layout{ 16 | self = [super initWithFrame:frame collectionViewLayout:layout]; 17 | if(self){ 18 | [self setUp]; 19 | } 20 | return self; 21 | } 22 | 23 | - (void)setUp{ 24 | 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo.xcodeproj/xcuserdata/lzx.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo.xcodeproj/xcuserdata/mac.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UINavigationController+ZXNavBarAllHiddenExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationController+ZXNavBarAllHiddenExtension.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/20. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UINavigationController (ZXNavBarAllHiddenExtension) 15 | 16 | /** 17 | 隐藏所有导航栏【可有效避免可能出现的状态栏颜色黑白切换或导航栏跳动的问题】(请在appdelegate的didFinishLaunchingWithOptions中设置,并确保在根控制器初始化之前,若导航控制器为ZXNavigationBarNavigationController或其子控制器,无需进行此项设置) 18 | */ 19 | + (void)zx_hideAllNavBar; 20 | 21 | /** 22 | 取消隐藏所有导航栏 23 | */ 24 | + (void)zx_removeAllNavBar; 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/ZXNavigationBarController+ZXNavSystemBarPopHandle.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBarController+ZXNavSystemBarPopHandle.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/5/29. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | //Thanks to @onegray https://github.com/onegray/UIViewController-BackButtonHandler Respect! 11 | 12 | #import "ZXNavigationBarController.h" 13 | 14 | NS_ASSUME_NONNULL_BEGIN 15 | @protocol ZXBackButtonHandlerProtocol 16 | @optional 17 | 18 | -(BOOL)zx_navSystemBarPopHandle; 19 | @end 20 | @interface UIViewController (ZXNavSystemBarPopHandle) 21 | 22 | @end 23 | 24 | NS_ASSUME_NONNULL_END 25 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoSystemBarViewController/DemoSystemBarViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoSystemBarViewController.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/11. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoSystemBarViewController.h" 10 | 11 | @implementation DemoSystemBarViewController 12 | - (void)viewDidLoad { 13 | [super viewDidLoad]; 14 | self.title = @"系统导航栏(继承于ZXNavigationBarController)"; 15 | self.zx_showSystemNavBar = YES; 16 | self.view.backgroundColor = [UIColor whiteColor]; 17 | 18 | UILabel *label = [[UILabel alloc]init]; 19 | label.frame = CGRectMake(0, 10, ZXScreenWidth, 20); 20 | label.textAlignment = NSTextAlignmentCenter; 21 | label.text = @"这是一个系统导航栏的控制器"; 22 | [self.view addSubview:label]; 23 | 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UINavigationController+ZXNavBarAllHiddenExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationController+ZXNavBarAllHiddenExtension.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/20. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UINavigationController (ZXNavBarAllHiddenExtension) 15 | 16 | /** 17 | 隐藏所有导航栏【可有效避免可能出现的状态栏颜色黑白切换或导航栏跳动的问题】(请在appdelegate的didFinishLaunchingWithOptions中设置,并确保在根控制器初始化之前,若导航控制器为ZXNavigationBarNavigationController或其子控制器,无需进行此项设置) 18 | */ 19 | + (void)zx_hideAllNavBar; 20 | 21 | /** 22 | 取消隐藏所有导航栏 23 | */ 24 | + (void)zx_removeAllNavBar; 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/Model/ZXNavHistoryStackModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackModel.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import 12 | typedef enum { 13 | ZXNavHistoryStackViewStyleLight = 0x00, // 历史堆栈浅色模式 14 | ZXNavHistoryStackViewStyleDark = 0x01, // 历史堆栈深色模式 15 | }ZXNavHistoryStackViewStyle; 16 | NS_ASSUME_NONNULL_BEGIN 17 | 18 | @interface ZXNavHistoryStackModel : NSObject 19 | @property (copy, nonatomic) NSString *title; 20 | @property (strong, nonatomic) UIViewController *viewController; 21 | @property (assign, nonatomic) BOOL isSelected; 22 | @property (assign, nonatomic) BOOL isLast; 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIView+ZXNavFrameExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+ZXNavFrameExtension.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.3.6 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIView (ZXNavFrameExtension) 15 | @property (nonatomic) CGFloat zx_x; 16 | @property (nonatomic) CGFloat zx_y; 17 | @property (nonatomic) CGFloat zx_width; 18 | @property (nonatomic) CGFloat zx_height; 19 | @property (nonatomic) CGFloat zx_right; 20 | @property (nonatomic) CGFloat zx_bottom; 21 | @property (nonatomic) CGFloat zx_centerX; 22 | @property (nonatomic) CGFloat zx_centerY; 23 | @property (nonatomic) CGPoint zx_origin; 24 | @property (nonatomic) CGSize zx_size; 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavTitleLabel.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavTitleLabel.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavTitleLabel.h" 11 | 12 | @implementation ZXNavTitleLabel 13 | 14 | - (void)setText:(NSString *)text{ 15 | [super setText:text]; 16 | [self noticeUpdateFrame]; 17 | } 18 | 19 | - (void)setAttributedText:(NSAttributedString *)attributedText{ 20 | [super setAttributedText:attributedText]; 21 | [self noticeUpdateFrame]; 22 | } 23 | 24 | - (void)setFont:(UIFont *)font{ 25 | [super setFont:font]; 26 | [self noticeUpdateFrame]; 27 | } 28 | 29 | - (void)noticeUpdateFrame{ 30 | if(self.zx_titleLabelFrameUpdateBlock){ 31 | self.zx_titleLabelFrameUpdateBlock(self); 32 | } 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/Model/ZXNavHistoryStackModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackModel.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import 12 | typedef enum { 13 | ZXNavHistoryStackViewStyleLight = 0x00, // 历史堆栈浅色模式 14 | ZXNavHistoryStackViewStyleDark = 0x01, // 历史堆栈深色模式 15 | }ZXNavHistoryStackViewStyle; 16 | NS_ASSUME_NONNULL_BEGIN 17 | 18 | @interface ZXNavHistoryStackModel : NSObject 19 | @property (copy, nonatomic) NSString *title; 20 | @property (strong, nonatomic) UIViewController *viewController; 21 | @property (assign, nonatomic) BOOL isSelected; 22 | @property (assign, nonatomic) BOOL isLast; 23 | @end 24 | 25 | NS_ASSUME_NONNULL_END 26 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIView+ZXNavFrameExtension.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+ZXNavFrameExtension.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.3.6 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface UIView (ZXNavFrameExtension) 15 | @property (nonatomic) CGFloat zx_x; 16 | @property (nonatomic) CGFloat zx_y; 17 | @property (nonatomic) CGFloat zx_width; 18 | @property (nonatomic) CGFloat zx_height; 19 | @property (nonatomic) CGFloat zx_right; 20 | @property (nonatomic) CGFloat zx_bottom; 21 | @property (nonatomic) CGFloat zx_centerX; 22 | @property (nonatomic) CGFloat zx_centerY; 23 | @property (nonatomic) CGPoint zx_origin; 24 | @property (nonatomic) CGSize zx_size; 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavTitleLabel.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavTitleLabel.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavTitleLabel.h" 11 | 12 | @implementation ZXNavTitleLabel 13 | 14 | - (void)setText:(NSString *)text{ 15 | [super setText:text]; 16 | [self noticeUpdateFrame]; 17 | } 18 | 19 | - (void)setAttributedText:(NSAttributedString *)attributedText{ 20 | [super setAttributedText:attributedText]; 21 | [self noticeUpdateFrame]; 22 | } 23 | 24 | - (void)setFont:(UIFont *)font{ 25 | [super setFont:font]; 26 | [self noticeUpdateFrame]; 27 | } 28 | 29 | - (void)noticeUpdateFrame{ 30 | if(self.zx_titleLabelFrameUpdateBlock){ 31 | self.zx_titleLabelFrameUpdateBlock(self); 32 | } 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIImage+ZXNavBundleExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ZXNavBundleExtension.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/11. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "UIImage+ZXNavBundleExtension.h" 11 | #import "ZXNavigationBar.h" 12 | @implementation UIImage (ZXNavBundleExtension) 13 | 14 | + (UIImage *)zx_imageFromBundleWithImageName:(NSString *)imageName{ 15 | static UIImage *image = nil; 16 | if (image == nil) { 17 | NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle bundleForClass:[ZXNavigationBar class]] pathForResource:@"ZXNavigationBar" ofType:@"bundle"]]; 18 | image = [[UIImage imageWithContentsOfFile:[bundle pathForResource:imageName ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; 19 | } 20 | return image; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIImage+ZXNavBundleExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ZXNavBundleExtension.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/11. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "UIImage+ZXNavBundleExtension.h" 11 | #import "ZXNavigationBar.h" 12 | @implementation UIImage (ZXNavBundleExtension) 13 | 14 | + (UIImage *)zx_imageFromBundleWithImageName:(NSString *)imageName{ 15 | static UIImage *image = nil; 16 | if (image == nil) { 17 | NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle bundleForClass:[ZXNavigationBar class]] pathForResource:@"ZXNavigationBar" ofType:@"bundle"]]; 18 | image = [[UIImage imageWithContentsOfFile:[bundle pathForResource:imageName ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; 19 | } 20 | return image; 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackContentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackContentView.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import "ZXNavHistoryStackView.h" 12 | #import "ZXNavHistoryStackModel.h" 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | 16 | @interface ZXNavHistoryStackContentView : UIView 17 | @property (strong, nonatomic) ZXNavHistoryStackView *zx_historyStackView; 18 | @property (strong, nonatomic) NSMutableArray *zx_historyStackArray; 19 | ///导航栏历史堆栈视图与屏幕左侧的距离,与返回按钮与屏幕左侧的距离相同,交由内部处理,修改此属性无效 20 | @property (assign, nonatomic) CGFloat zx_historyStackViewLeft; 21 | ///导航栏历史堆栈视图显示样式 22 | @property (assign, nonatomic) ZXNavHistoryStackViewStyle zx_historyStackViewStyle; 23 | - (instancetype)zx_show; 24 | - (void)zx_hide; 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCustomTitleViewViewController/DemoCustomTitleViewViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCustomTitleViewViewController.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoCustomTitleViewViewController.h" 10 | #import "DemoCustomTitleView.h" 11 | @implementation DemoCustomTitleViewViewController 12 | - (void)viewDidLoad { 13 | [super viewDidLoad]; 14 | [self setUpNav]; 15 | [self setUpView]; 16 | } 17 | 18 | - (void)setUpNav{ 19 | DemoCustomTitleView *customTitleView = [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([DemoCustomTitleView class]) owner:nil options:nil]lastObject]; 20 | [self zx_addCustomTitleView:customTitleView]; 21 | 22 | [self zx_setRightBtnWithText:@"测试" clickedBlock:^(ZXNavItemBtn * _Nonnull btn) { 23 | 24 | }]; 25 | } 26 | 27 | - (void)setUpView{ 28 | self.view.backgroundColor = [UIColor whiteColor]; 29 | } 30 | @end 31 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackContentView.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackContentView.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import "ZXNavHistoryStackView.h" 12 | #import "ZXNavHistoryStackModel.h" 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | 16 | @interface ZXNavHistoryStackContentView : UIView 17 | @property (strong, nonatomic) ZXNavHistoryStackView *zx_historyStackView; 18 | @property (strong, nonatomic) NSMutableArray *zx_historyStackArray; 19 | ///导航栏历史堆栈视图与屏幕左侧的距离,与返回按钮与屏幕左侧的距离相同,交由内部处理,修改此属性无效 20 | @property (assign, nonatomic) CGFloat zx_historyStackViewLeft; 21 | ///导航栏历史堆栈视图显示样式 22 | @property (assign, nonatomic) ZXNavHistoryStackViewStyle zx_historyStackViewStyle; 23 | - (instancetype)zx_show; 24 | - (void)zx_hide; 25 | @end 26 | 27 | NS_ASSUME_NONNULL_END 28 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/NSAttributedString+ZXNavCalcSizeExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+ZXNavCalcSizeExtension.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/10/23. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "NSAttributedString+ZXNavCalcSizeExtension.h" 11 | 12 | @implementation NSAttributedString (ZXNavCalcSizeExtension) 13 | - (CGFloat)zx_getAttrRectWidthWithLimitH:(CGFloat)limitH fontSize:(CGFloat)fontSize{ 14 | UILabel *label = [[UILabel alloc]init]; 15 | label.font = [UIFont systemFontOfSize:fontSize]; 16 | label.attributedText = self; 17 | return [label sizeThatFits:CGSizeMake(MAXFLOAT, limitH)].width; 18 | } 19 | - (CGFloat)zx_getAttrRectHeightWithLimitW:(CGFloat)limitW fontSize:(CGFloat)fontSize{ 20 | UILabel *label = [[UILabel alloc]init]; 21 | label.font = [UIFont systemFontOfSize:fontSize]; 22 | label.attributedText = self; 23 | return [label sizeThatFits:CGSizeMake(limitW,MAXFLOAT )].height; 24 | } 25 | @end 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 李兆祥 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIImage+ZXNavColorRender.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ZXNavColorRender.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "UIImage+ZXNavColorRender.h" 11 | 12 | @implementation UIImage (ZXNavColorRender) 13 | - (UIImage *)zx_renderingColor:(UIColor *)color{ 14 | UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); 15 | CGContextRef context = UIGraphicsGetCurrentContext(); 16 | CGContextTranslateCTM(context, 0, self.size.height); 17 | CGContextScaleCTM(context, 1.0, -1.0); 18 | CGContextSetBlendMode(context, kCGBlendModeNormal); 19 | CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); 20 | CGContextClipToMask(context, rect, self.CGImage); 21 | [color setFill]; 22 | CGContextFillRect(context, rect); 23 | UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext(); 24 | UIGraphicsEndImageContext(); 25 | return renderedImage; 26 | } 27 | @end 28 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/NSAttributedString+ZXNavCalcSizeExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSAttributedString+ZXNavCalcSizeExtension.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/10/23. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "NSAttributedString+ZXNavCalcSizeExtension.h" 11 | 12 | @implementation NSAttributedString (ZXNavCalcSizeExtension) 13 | - (CGFloat)zx_getAttrRectWidthWithLimitH:(CGFloat)limitH fontSize:(CGFloat)fontSize{ 14 | UILabel *label = [[UILabel alloc]init]; 15 | label.font = [UIFont systemFontOfSize:fontSize]; 16 | label.attributedText = self; 17 | return [label sizeThatFits:CGSizeMake(MAXFLOAT, limitH)].width; 18 | } 19 | - (CGFloat)zx_getAttrRectHeightWithLimitW:(CGFloat)limitW fontSize:(CGFloat)fontSize{ 20 | UILabel *label = [[UILabel alloc]init]; 21 | label.font = [UIFont systemFontOfSize:fontSize]; 22 | label.attributedText = self; 23 | return [label sizeThatFits:CGSizeMake(limitW,MAXFLOAT )].height; 24 | } 25 | @end 26 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoSystemBarViewController/DemoPublicSystemBarViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoPublicSystemBarViewController.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/8/4. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoPublicSystemBarViewController.h" 10 | #import "DemoXibViewController.h" 11 | 12 | @interface DemoPublicSystemBarViewController () 13 | 14 | @end 15 | 16 | @implementation DemoPublicSystemBarViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | self.title = @"系统导航栏"; 21 | self.view.backgroundColor = [UIColor whiteColor]; 22 | 23 | UILabel *label = [[UILabel alloc]init]; 24 | label.frame = CGRectMake(0, 10, [UIScreen mainScreen].bounds.size.width, 20); 25 | label.textAlignment = NSTextAlignmentCenter; 26 | label.text = @"这是一个系统导航栏的控制器"; 27 | [self.view addSubview:label]; 28 | 29 | //注意,因导航栏默认被隐藏,请手动设置显示导航栏 30 | self.navigationController.navigationBarHidden = NO; 31 | //如果希望view从导航栏下方开始,请设置导航栏为不透明 32 | self.navigationController.navigationBar.translucent = NO; 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIImage+ZXNavColorRender.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ZXNavColorRender.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "UIImage+ZXNavColorRender.h" 11 | 12 | @implementation UIImage (ZXNavColorRender) 13 | - (UIImage *)zx_renderingColor:(UIColor *)color{ 14 | UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); 15 | CGContextRef context = UIGraphicsGetCurrentContext(); 16 | CGContextTranslateCTM(context, 0, self.size.height); 17 | CGContextScaleCTM(context, 1.0, -1.0); 18 | CGContextSetBlendMode(context, kCGBlendModeNormal); 19 | CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); 20 | CGContextClipToMask(context, rect, self.CGImage); 21 | [color setFill]; 22 | CGContextFillRect(context, rect); 23 | UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext(); 24 | UIGraphicsEndImageContext(); 25 | return renderedImage; 26 | } 27 | @end 28 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/NSString+ZXNavCalcSizeExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+ZXNavCalcSizeExtension.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "NSString+ZXNavCalcSizeExtension.h" 11 | 12 | @implementation NSString (ZXNavCalcSizeExtension) 13 | - (CGFloat)zx_getRectWidthWithLimitH:(CGFloat)limitH fontSize:(CGFloat)fontSize{ 14 | CGRect rect = [self boundingRectWithSize:CGSizeMake(MAXFLOAT, limitH) 15 | options:NSStringDrawingUsesLineFragmentOrigin 16 | attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]} 17 | context:nil]; 18 | return rect.size.width; 19 | } 20 | - (CGFloat)zx_getRectHeightWithLimitW:(CGFloat)limitW fontSize:(CGFloat)fontSize{ 21 | CGRect rect = [self boundingRectWithSize:CGSizeMake(limitW,MAXFLOAT ) 22 | options:NSStringDrawingUsesLineFragmentOrigin 23 | attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]} 24 | context:nil]; 25 | return rect.size.height; 26 | } 27 | @end 28 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/NSString+ZXNavCalcSizeExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+ZXNavCalcSizeExtension.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "NSString+ZXNavCalcSizeExtension.h" 11 | 12 | @implementation NSString (ZXNavCalcSizeExtension) 13 | - (CGFloat)zx_getRectWidthWithLimitH:(CGFloat)limitH fontSize:(CGFloat)fontSize{ 14 | CGRect rect = [self boundingRectWithSize:CGSizeMake(MAXFLOAT, limitH) 15 | options:NSStringDrawingUsesLineFragmentOrigin 16 | attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]} 17 | context:nil]; 18 | return rect.size.width; 19 | } 20 | - (CGFloat)zx_getRectHeightWithLimitW:(CGFloat)limitW fontSize:(CGFloat)fontSize{ 21 | CGRect rect = [self boundingRectWithSize:CGSizeMake(limitW,MAXFLOAT ) 22 | options:NSStringDrawingUsesLineFragmentOrigin 23 | attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontSize]} 24 | context:nil]; 25 | return rect.size.height; 26 | } 27 | @end 28 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemoUITests/ZXNavigationBarDemoUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBarDemoUITests.m 3 | // ZXNavigationBarDemoUITests 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ZXNavigationBarDemoUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ZXNavigationBarDemoUITests 16 | 17 | - (void)setUp { 18 | // Put setup code here. This method is called before the invocation of each test method in the class. 19 | 20 | // In UI tests it is usually best to stop immediately when a failure occurs. 21 | self.continueAfterFailure = NO; 22 | 23 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 24 | [[[XCUIApplication alloc] init] launch]; 25 | 26 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 27 | } 28 | 29 | - (void)tearDown { 30 | // Put teardown code here. This method is called after the invocation of each test method in the class. 31 | } 32 | 33 | - (void)testExample { 34 | // Use recording to get started writing UI tests. 35 | // Use XCTAssert and related functions to verify your tests produce the correct results. 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCustomNavViewController/DemoCustomNavViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCustomNavViewController.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoCustomNavViewController.h" 10 | #import "DemoCustomNav.h" 11 | @interface DemoCustomNavViewController() 12 | @property (weak, nonatomic) UILabel *noticeLabel; 13 | @end 14 | @implementation DemoCustomNavViewController 15 | - (void)viewDidLoad { 16 | [super viewDidLoad]; 17 | [self setUpNav]; 18 | [self setUpView]; 19 | } 20 | 21 | - (void)setUpNav{ 22 | DemoCustomNav *customNav = [[[NSBundle mainBundle]loadNibNamed:NSStringFromClass([DemoCustomNav class]) owner:nil options:nil]lastObject]; 23 | [self zx_addCustomNavBar:customNav]; 24 | } 25 | 26 | - (void)setUpView{ 27 | self.view.backgroundColor = [UIColor whiteColor]; 28 | UILabel *noticeLabel = [[UILabel alloc]init]; 29 | noticeLabel.textAlignment = NSTextAlignmentCenter; 30 | noticeLabel.text = @"使用侧滑手势可以返回主页"; 31 | noticeLabel.textColor = [UIColor lightGrayColor]; 32 | [self.view addSubview:noticeLabel]; 33 | self.noticeLabel = noticeLabel; 34 | } 35 | 36 | - (void)viewDidLayoutSubviews{ 37 | [super viewDidLayoutSubviews]; 38 | self.noticeLabel.frame = CGRectMake(0, ZXNavBarHeight + 10, self.view.frame.size.width, 30); 39 | } 40 | @end 41 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarNavigationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBarNavigationController.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/5/29. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavigationBarNavigationController : UINavigationController 15 | 16 | /** 17 | 是否禁用push控制器自动隐藏tabbar 18 | */ 19 | @property (assign, nonatomic)BOOL zx_disableAutoHidesBottomBarWhenPushed; 20 | 21 | /** 22 | pop返回手势对象 23 | */ 24 | @property (strong, nonatomic, readonly) UIPanGestureRecognizer *zx_popGestureRecognizer; 25 | 26 | /** 27 | 是否禁用全屏pop手势,若禁用,则pop触发范围为屏幕宽度的十分之一 28 | */ 29 | @property (assign, nonatomic)BOOL zx_disableFullScreenGesture; 30 | 31 | 32 | /** 33 | pop手势的触发范围比例,0-1,默认为1,即代表全屏触发 34 | */ 35 | @property (assign, nonatomic) CGFloat zx_popGestureCoverRatio; 36 | 37 | /** 38 | 监听自定义pop手势进度。currentViewController代表当前正在pop的控制器,popOffsetProgress范围为0-1,0代表即将开始pop,1代表完成pop 39 | */ 40 | @property(copy, nonatomic)void(^zx_handleCustomPopGesture)(UIViewController *currentViewController,CGFloat popOffsetProgress); 41 | 42 | /** 43 | pop手势是否支持多层级的手势同时触发,默认为否 44 | */ 45 | @property(copy, nonatomic)BOOL(^zx_popGestureShouldRecognizeSimultaneously)(UIGestureRecognizer *otherGestureRecognizer); 46 | 47 | /** 48 | 拦截导航控制器侧滑返回手势,若返回NO,则禁止pop; 49 | topViewController:当前控制器 50 | */ 51 | @property(copy, nonatomic)BOOL(^zx_navHandlePopGestureBlock)(UIViewController *topViewController); 52 | @end 53 | 54 | NS_ASSUME_NONNULL_END 55 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarNavigationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBarNavigationController.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/5/29. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavigationBarNavigationController : UINavigationController 15 | 16 | /** 17 | 是否禁用push控制器自动隐藏tabbar 18 | */ 19 | @property (assign, nonatomic)BOOL zx_disableAutoHidesBottomBarWhenPushed; 20 | 21 | /** 22 | pop返回手势对象 23 | */ 24 | @property (strong, nonatomic, readonly) UIPanGestureRecognizer *zx_popGestureRecognizer; 25 | 26 | /** 27 | 是否禁用全屏pop手势,若禁用,则pop触发范围为屏幕宽度的十分之一 28 | */ 29 | @property (assign, nonatomic)BOOL zx_disableFullScreenGesture; 30 | 31 | 32 | /** 33 | pop手势的触发范围比例,0-1,默认为1,即代表全屏触发 34 | */ 35 | @property (assign, nonatomic) CGFloat zx_popGestureCoverRatio; 36 | 37 | /** 38 | 监听自定义pop手势进度。currentViewController代表当前正在pop的控制器,popOffsetProgress范围为0-1,0代表即将开始pop,1代表完成pop 39 | */ 40 | @property(copy, nonatomic)void(^zx_handleCustomPopGesture)(UIViewController *currentViewController,CGFloat popOffsetProgress); 41 | 42 | /** 43 | pop手势是否支持多层级的手势同时触发,默认为否 44 | */ 45 | @property(copy, nonatomic)BOOL(^zx_popGestureShouldRecognizeSimultaneously)(UIGestureRecognizer *otherGestureRecognizer); 46 | 47 | /** 48 | 拦截导航控制器侧滑返回手势,若返回NO,则禁止pop; 49 | topViewController:当前控制器 50 | */ 51 | @property(copy, nonatomic)BOOL(^zx_navHandlePopGestureBlock)(UIViewController *topViewController); 52 | @end 53 | 54 | NS_ASSUME_NONNULL_END 55 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIUserInterfaceStyle 6 | Light 7 | NSAppTransportSecurity 8 | 9 | NSAllowsArbitraryLoads 10 | 11 | 12 | CFBundleDevelopmentRegion 13 | $(DEVELOPMENT_LANGUAGE) 14 | CFBundleExecutable 15 | $(EXECUTABLE_NAME) 16 | CFBundleIdentifier 17 | $(PRODUCT_BUNDLE_IDENTIFIER) 18 | CFBundleInfoDictionaryVersion 19 | 6.0 20 | CFBundleName 21 | $(PRODUCT_NAME) 22 | CFBundlePackageType 23 | APPL 24 | CFBundleShortVersionString 25 | 1.0 26 | CFBundleVersion 27 | 1 28 | LSRequiresIPhoneOS 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UINavigationController+ZXNavBarAllHiddenExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationController+ZXNavBarAllHiddenExtension.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/20. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "UINavigationController+ZXNavBarAllHiddenExtension.h" 11 | #import 12 | static BOOL isHideAllNavBar = NO; 13 | @implementation UINavigationController (ZXNavBarAllHiddenExtension) 14 | + (void)zx_hideAllNavBar{ 15 | isHideAllNavBar = YES; 16 | zx_nav_swizzleMethod([self class], @selector(pushViewController:animated:), @selector(swizzled_pushViewController:animated:)); 17 | } 18 | 19 | + (void)zx_removeAllNavBar{ 20 | isHideAllNavBar = NO; 21 | } 22 | 23 | - (void)swizzled_pushViewController:(UIViewController *)viewController animated:(BOOL)animated{ 24 | [self swizzled_pushViewController:viewController animated:animated]; 25 | Class zxNavVcCls1 = NSClassFromString(@"ZXNavigationBarController"); 26 | Class zxNavVcCls2 = NSClassFromString(@"ZXNavigationBarTableViewController"); 27 | if(isHideAllNavBar && ([viewController isKindOfClass:zxNavVcCls1] || [viewController isKindOfClass:zxNavVcCls2])){ 28 | self.navigationBarHidden = YES; 29 | } 30 | } 31 | 32 | void zx_nav_swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector){ 33 | Method originalMethod = class_getInstanceMethod(class, originalSelector); 34 | Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); 35 | BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); 36 | 37 | if (didAddMethod) { 38 | class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); 39 | } 40 | else { 41 | method_exchangeImplementations(originalMethod, swizzledMethod); 42 | } 43 | 44 | } 45 | @end 46 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UINavigationController+ZXNavBarAllHiddenExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UINavigationController+ZXNavBarAllHiddenExtension.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/20. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "UINavigationController+ZXNavBarAllHiddenExtension.h" 11 | #import 12 | static BOOL isHideAllNavBar = NO; 13 | @implementation UINavigationController (ZXNavBarAllHiddenExtension) 14 | + (void)zx_hideAllNavBar{ 15 | isHideAllNavBar = YES; 16 | zx_nav_swizzleMethod([self class], @selector(pushViewController:animated:), @selector(swizzled_pushViewController:animated:)); 17 | } 18 | 19 | + (void)zx_removeAllNavBar{ 20 | isHideAllNavBar = NO; 21 | } 22 | 23 | - (void)swizzled_pushViewController:(UIViewController *)viewController animated:(BOOL)animated{ 24 | [self swizzled_pushViewController:viewController animated:animated]; 25 | Class zxNavVcCls1 = NSClassFromString(@"ZXNavigationBarController"); 26 | Class zxNavVcCls2 = NSClassFromString(@"ZXNavigationBarTableViewController"); 27 | if(isHideAllNavBar && ([viewController isKindOfClass:zxNavVcCls1] || [viewController isKindOfClass:zxNavVcCls2])){ 28 | self.navigationBarHidden = YES; 29 | } 30 | } 31 | 32 | void zx_nav_swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector){ 33 | Method originalMethod = class_getInstanceMethod(class, originalSelector); 34 | Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector); 35 | BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); 36 | 37 | if (didAddMethod) { 38 | class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); 39 | } 40 | else { 41 | method_exchangeImplementations(originalMethod, swizzledMethod); 42 | } 43 | 44 | } 45 | @end 46 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/ZXNavigationBarController+ZXNavSystemBarPopHandle.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBarController+ZXNavSystemBarPopHandle.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/5/29. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | //Thanks to @onegray https://github.com/onegray/UIViewController-BackButtonHandler Respect! 11 | 12 | #import "ZXNavigationBarController+ZXNavSystemBarPopHandle.h" 13 | #import 14 | 15 | @implementation UIViewController (ZXNavSystemBarPopHandle) 16 | 17 | @end 18 | 19 | @implementation UINavigationController (ZXNavSystemBarPopHandle) 20 | 21 | + (void)load { 22 | Method originalMethod = class_getInstanceMethod([self class], @selector(navigationBar:shouldPopItem:)); 23 | Method overloadingMethod = class_getInstanceMethod([self class], @selector(overloaded_navigationBar:shouldPopItem:)); 24 | method_setImplementation(originalMethod, method_getImplementation(overloadingMethod)); 25 | } 26 | 27 | - (BOOL)overloaded_navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item { 28 | if([self.viewControllers count] < [navigationBar.items count]) { 29 | return YES; 30 | } 31 | BOOL shouldPop = YES; 32 | UIViewController* vc = [self topViewController]; 33 | if([vc respondsToSelector:@selector(zx_navSystemBarPopHandle)]) { 34 | shouldPop = [vc zx_navSystemBarPopHandle]; 35 | } 36 | if(shouldPop) { 37 | dispatch_async(dispatch_get_main_queue(), ^{ 38 | [self popViewControllerAnimated:YES]; 39 | }); 40 | } else { 41 | // Workaround for iOS7.1. Thanks to @boliva - http://stackoverflow.com/posts/comments/34452906 42 | for(UIView *subview in [navigationBar subviews]) { 43 | if(0. < subview.alpha && subview.alpha < 1.) { 44 | [UIView animateWithDuration:.25 animations:^{ 45 | subview.alpha = 1.; 46 | }]; 47 | } 48 | } 49 | } 50 | return NO; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/ZXNavigationBarController+ZXNavSystemBarPopHandle.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBarController+ZXNavSystemBarPopHandle.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/5/29. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | //Thanks to @onegray https://github.com/onegray/UIViewController-BackButtonHandler Respect! 11 | 12 | #import "ZXNavigationBarController+ZXNavSystemBarPopHandle.h" 13 | #import 14 | 15 | @implementation UIViewController (ZXNavSystemBarPopHandle) 16 | 17 | @end 18 | 19 | @implementation UINavigationController (ZXNavSystemBarPopHandle) 20 | 21 | + (void)load { 22 | Method originalMethod = class_getInstanceMethod([self class], @selector(navigationBar:shouldPopItem:)); 23 | Method overloadingMethod = class_getInstanceMethod([self class], @selector(overloaded_navigationBar:shouldPopItem:)); 24 | method_setImplementation(originalMethod, method_getImplementation(overloadingMethod)); 25 | } 26 | 27 | - (BOOL)overloaded_navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item { 28 | if([self.viewControllers count] < [navigationBar.items count]) { 29 | return YES; 30 | } 31 | BOOL shouldPop = YES; 32 | UIViewController* vc = [self topViewController]; 33 | if([vc respondsToSelector:@selector(zx_navSystemBarPopHandle)]) { 34 | shouldPop = [vc zx_navSystemBarPopHandle]; 35 | } 36 | if(shouldPop) { 37 | dispatch_async(dispatch_get_main_queue(), ^{ 38 | [self popViewControllerAnimated:YES]; 39 | }); 40 | } else { 41 | // Workaround for iOS7.1. Thanks to @boliva - http://stackoverflow.com/posts/comments/34452906 42 | for(UIView *subview in [navigationBar subviews]) { 43 | if(0. < subview.alpha && subview.alpha < 1.) { 44 | [UIView animateWithDuration:.25 animations:^{ 45 | subview.alpha = 1.; 46 | }]; 47 | } 48 | } 49 | } 50 | return NO; 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackCell.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavHistoryStackCell.h" 11 | #import "ZXNavHistoryStackModel.h" 12 | #import "ZXNavigationBarDefine.h" 13 | @interface ZXNavHistoryStackCell() 14 | @property (strong, nonatomic) UILabel *contentLabel; 15 | @property (strong, nonatomic) UIView *lineView; 16 | @end 17 | @implementation ZXNavHistoryStackCell 18 | 19 | - (instancetype)initWithFrame:(CGRect)frame{ 20 | self = [super initWithFrame:frame]; 21 | if(self){ 22 | [self setUp]; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)setUp{ 28 | self.contentLabel = [[UILabel alloc]init]; 29 | self.contentLabel.font = [UIFont systemFontOfSize:17]; 30 | self.lineView = [[UIView alloc]init]; 31 | self.lineView.backgroundColor = [UIColor redColor]; 32 | [self.contentView addSubview:self.contentLabel]; 33 | [self.contentView addSubview:self.lineView]; 34 | 35 | } 36 | 37 | - (void)layoutSubviews{ 38 | [super layoutSubviews]; 39 | self.contentLabel.frame = CGRectMake(ZXNavHistoryStackCellTitleX, 0, self.frame.size.width - ZXNavHistoryStackCellTitleX * 2, self.frame.size.height); 40 | self.lineView.frame = CGRectMake(0, self.frame.size.height - 0.5, self.frame.size.width, 0.5); 41 | self.lineView.backgroundColor = ZXNavDefalutLineColor; 42 | } 43 | 44 | - (void)setHistoryStackModel:(ZXNavHistoryStackModel *)historyStackModel{ 45 | _historyStackModel = historyStackModel; 46 | self.contentLabel.text = historyStackModel.title; 47 | if(self.historyStackViewStyle == ZXNavHistoryStackViewStyleLight){ 48 | self.contentView.backgroundColor = ZXNavHistoryStackViewStyleLightBackgroundColor; 49 | self.contentLabel.textColor = [UIColor blackColor]; 50 | }else{ 51 | self.contentLabel.textColor = [UIColor whiteColor]; 52 | self.contentView.backgroundColor = ZXNavHistoryStackViewStyleDarkBackgroundColor; 53 | } 54 | if(historyStackModel.isSelected){ 55 | if(self.historyStackViewStyle == ZXNavHistoryStackViewStyleLight){ 56 | self.contentView.backgroundColor = ZXNavHistoryStackViewStyleLightSelectedColor; 57 | }else{ 58 | self.contentView.backgroundColor = ZXNavHistoryStackViewStyleDarkSelectedColor; 59 | } 60 | } 61 | } 62 | @end 63 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackCell.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavHistoryStackCell.h" 11 | #import "ZXNavHistoryStackModel.h" 12 | #import "ZXNavigationBarDefine.h" 13 | @interface ZXNavHistoryStackCell() 14 | @property (strong, nonatomic) UILabel *contentLabel; 15 | @property (strong, nonatomic) UIView *lineView; 16 | @end 17 | @implementation ZXNavHistoryStackCell 18 | 19 | - (instancetype)initWithFrame:(CGRect)frame{ 20 | self = [super initWithFrame:frame]; 21 | if(self){ 22 | [self setUp]; 23 | } 24 | return self; 25 | } 26 | 27 | - (void)setUp{ 28 | self.contentLabel = [[UILabel alloc]init]; 29 | self.contentLabel.font = [UIFont systemFontOfSize:17]; 30 | self.lineView = [[UIView alloc]init]; 31 | self.lineView.backgroundColor = [UIColor redColor]; 32 | [self.contentView addSubview:self.contentLabel]; 33 | [self.contentView addSubview:self.lineView]; 34 | 35 | } 36 | 37 | - (void)layoutSubviews{ 38 | [super layoutSubviews]; 39 | self.contentLabel.frame = CGRectMake(ZXNavHistoryStackCellTitleX, 0, self.frame.size.width - ZXNavHistoryStackCellTitleX * 2, self.frame.size.height); 40 | self.lineView.frame = CGRectMake(0, self.frame.size.height - 0.5, self.frame.size.width, 0.5); 41 | self.lineView.backgroundColor = ZXNavDefalutLineColor; 42 | } 43 | 44 | - (void)setHistoryStackModel:(ZXNavHistoryStackModel *)historyStackModel{ 45 | _historyStackModel = historyStackModel; 46 | self.contentLabel.text = historyStackModel.title; 47 | if(self.historyStackViewStyle == ZXNavHistoryStackViewStyleLight){ 48 | self.contentView.backgroundColor = ZXNavHistoryStackViewStyleLightBackgroundColor; 49 | self.contentLabel.textColor = [UIColor blackColor]; 50 | }else{ 51 | self.contentLabel.textColor = [UIColor whiteColor]; 52 | self.contentView.backgroundColor = ZXNavHistoryStackViewStyleDarkBackgroundColor; 53 | } 54 | if(historyStackModel.isSelected){ 55 | if(self.historyStackViewStyle == ZXNavHistoryStackViewStyleLight){ 56 | self.contentView.backgroundColor = ZXNavHistoryStackViewStyleLightSelectedColor; 57 | }else{ 58 | self.contentView.backgroundColor = ZXNavHistoryStackViewStyleDarkSelectedColor; 59 | } 60 | } 61 | } 62 | @end 63 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "DemoListViewController.h" 11 | #import "ZXNavigationBarNavigationController.h" 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | UIWindow *window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds]; 21 | DemoListViewController *vc = [[DemoListViewController alloc]init]; 22 | ZXNavigationBarNavigationController *nav = [[ZXNavigationBarNavigationController alloc]initWithRootViewController:vc]; 23 | window.rootViewController = nav; 24 | [window makeKeyAndVisible]; 25 | self.window = window; 26 | return YES; 27 | } 28 | 29 | 30 | - (void)applicationWillResignActive:(UIApplication *)application { 31 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 32 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 33 | } 34 | 35 | 36 | - (void)applicationDidEnterBackground:(UIApplication *)application { 37 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 38 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 39 | } 40 | 41 | 42 | - (void)applicationWillEnterForeground:(UIApplication *)application { 43 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 44 | } 45 | 46 | 47 | - (void)applicationDidBecomeActive:(UIApplication *)application { 48 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 49 | } 50 | 51 | 52 | - (void)applicationWillTerminate:(UIApplication *)application { 53 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 54 | } 55 | 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIView+ZXNavFrameExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+ZXNavFrameExtension.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "UIView+ZXNavFrameExtension.h" 11 | 12 | @implementation UIView (ZXNavFrameExtension) 13 | - (CGFloat)zx_x{ 14 | return self.frame.origin.x; 15 | } 16 | 17 | - (void)setZx_x:(CGFloat)zx_x{ 18 | self.frame = CGRectMake(zx_x, self.zx_y, self.zx_width, self.zx_height); 19 | } 20 | 21 | - (CGFloat)zx_y{ 22 | return self.frame.origin.y; 23 | } 24 | 25 | - (void)setZx_y:(CGFloat)zx_y{ 26 | self.frame = CGRectMake(self.zx_x, zx_y, self.zx_width, self.zx_height); 27 | } 28 | 29 | - (CGFloat)zx_width{ 30 | return self.frame.size.width; 31 | } 32 | 33 | - (void)setZx_width:(CGFloat)zx_width{ 34 | self.frame = CGRectMake(self.zx_x, self.zx_y, zx_width, self.zx_height); 35 | } 36 | 37 | - (CGFloat)zx_height{ 38 | return self.frame.size.height; 39 | } 40 | 41 | - (void)setZx_height:(CGFloat)zx_height{ 42 | self.frame = CGRectMake(self.zx_x, self.zx_y, self.zx_width, zx_height); 43 | } 44 | 45 | - (CGFloat)zx_right{ 46 | return self.frame.origin.x + self.frame.size.width; 47 | } 48 | 49 | - (void)setZx_right:(CGFloat)zx_right{ 50 | CGRect frame = self.frame; 51 | frame.origin.x = zx_right - frame.size.width; 52 | self.frame = frame; 53 | } 54 | 55 | - (CGFloat)zx_bottom{ 56 | return self.frame.origin.y + self.frame.size.height; 57 | } 58 | 59 | - (void)setZx_bottom:(CGFloat)zx_bottom{ 60 | CGRect frame = self.frame; 61 | frame.origin.y = zx_bottom - frame.size.height; 62 | self.frame = frame; 63 | } 64 | 65 | - (CGFloat)zx_centerX{ 66 | return self.center.x; 67 | } 68 | 69 | - (void)setZx_centerX:(CGFloat)zx_centerX{ 70 | self.center = CGPointMake(zx_centerX, self.center.y); 71 | } 72 | 73 | - (CGFloat)zx_centerY{ 74 | return self.center.y; 75 | } 76 | 77 | - (void)setZx_centerY:(CGFloat)zx_centerY{ 78 | self.center = CGPointMake(self.center.x, zx_centerY); 79 | } 80 | 81 | - (CGPoint)zx_origin{ 82 | return self.frame.origin; 83 | } 84 | 85 | - (void)setZx_origin:(CGPoint)zx_origin{ 86 | CGRect frame = self.frame; 87 | frame.origin = zx_origin; 88 | self.frame = frame; 89 | } 90 | 91 | - (CGSize)zx_size{ 92 | return self.frame.size; 93 | } 94 | 95 | - (void)setZx_size:(CGSize)zx_size{ 96 | CGRect frame = self.frame; 97 | frame.size = zx_size; 98 | self.frame = frame; 99 | } 100 | @end 101 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarHelper/ZXNavigationBarCategory/UIView+ZXNavFrameExtension.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+ZXNavFrameExtension.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "UIView+ZXNavFrameExtension.h" 11 | 12 | @implementation UIView (ZXNavFrameExtension) 13 | - (CGFloat)zx_x{ 14 | return self.frame.origin.x; 15 | } 16 | 17 | - (void)setZx_x:(CGFloat)zx_x{ 18 | self.frame = CGRectMake(zx_x, self.zx_y, self.zx_width, self.zx_height); 19 | } 20 | 21 | - (CGFloat)zx_y{ 22 | return self.frame.origin.y; 23 | } 24 | 25 | - (void)setZx_y:(CGFloat)zx_y{ 26 | self.frame = CGRectMake(self.zx_x, zx_y, self.zx_width, self.zx_height); 27 | } 28 | 29 | - (CGFloat)zx_width{ 30 | return self.frame.size.width; 31 | } 32 | 33 | - (void)setZx_width:(CGFloat)zx_width{ 34 | self.frame = CGRectMake(self.zx_x, self.zx_y, zx_width, self.zx_height); 35 | } 36 | 37 | - (CGFloat)zx_height{ 38 | return self.frame.size.height; 39 | } 40 | 41 | - (void)setZx_height:(CGFloat)zx_height{ 42 | self.frame = CGRectMake(self.zx_x, self.zx_y, self.zx_width, zx_height); 43 | } 44 | 45 | - (CGFloat)zx_right{ 46 | return self.frame.origin.x + self.frame.size.width; 47 | } 48 | 49 | - (void)setZx_right:(CGFloat)zx_right{ 50 | CGRect frame = self.frame; 51 | frame.origin.x = zx_right - frame.size.width; 52 | self.frame = frame; 53 | } 54 | 55 | - (CGFloat)zx_bottom{ 56 | return self.frame.origin.y + self.frame.size.height; 57 | } 58 | 59 | - (void)setZx_bottom:(CGFloat)zx_bottom{ 60 | CGRect frame = self.frame; 61 | frame.origin.y = zx_bottom - frame.size.height; 62 | self.frame = frame; 63 | } 64 | 65 | - (CGFloat)zx_centerX{ 66 | return self.center.x; 67 | } 68 | 69 | - (void)setZx_centerX:(CGFloat)zx_centerX{ 70 | self.center = CGPointMake(zx_centerX, self.center.y); 71 | } 72 | 73 | - (CGFloat)zx_centerY{ 74 | return self.center.y; 75 | } 76 | 77 | - (void)setZx_centerY:(CGFloat)zx_centerY{ 78 | self.center = CGPointMake(self.center.x, zx_centerY); 79 | } 80 | 81 | - (CGPoint)zx_origin{ 82 | return self.frame.origin; 83 | } 84 | 85 | - (void)setZx_origin:(CGPoint)zx_origin{ 86 | CGRect frame = self.frame; 87 | frame.origin = zx_origin; 88 | self.frame = frame; 89 | } 90 | 91 | - (CGSize)zx_size{ 92 | return self.frame.size; 93 | } 94 | 95 | - (void)setZx_size:(CGSize)zx_size{ 96 | CGRect frame = self.frame; 97 | frame.size = zx_size; 98 | self.frame = frame; 99 | } 100 | @end 101 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavItemBtn.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavItemBtn.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavItemBtn : UIButton 15 | ///是否禁止设置title和attributedTitle 16 | @property (assign, nonatomic, readonly)BOOL zx_disableSetTitle; 17 | ///NavItemBtn的frame更新回调 18 | @property (copy, nonatomic) void (^zx_barItemBtnFrameUpdateBlock)(ZXNavItemBtn *barItemBtn); 19 | ///设置NavItemBtn的image颜色 20 | @property (strong, nonatomic, nullable)UIColor *zx_imageColor; 21 | ///设置NavItemBtn的tintColor 22 | @property (strong, nonatomic, nullable)UIColor *zx_tintColor; 23 | ///设置NavItemBtn的tintColor仅用于UIControlStateNormal状态(请在zx_imageColor和zx_tintColor之前设置),默认为NO 24 | @property (assign, nonatomic)UIColor *zx_useTintColorOnlyInStateNormal; 25 | ///设置NavItemBtn的字体大小 26 | @property (assign, nonatomic)CGFloat zx_fontSize; 27 | ///禁止自动调整按钮图片和文字的布局,若要使contentEdgeInsets、titleEdgeInsets、imageEdgeInsets等,则需要将此属性设置为NO 28 | @property (assign, nonatomic)BOOL zx_disableAutoLayoutImageAndTitle; 29 | ///设置NavItemBtn的固定宽度,若设置,则自动计算宽度无效,若要恢复初始值,可设置为-1 30 | @property (assign, nonatomic)CGFloat zx_fixWidth; 31 | ///设置NavItemBtn的固定高度,若设置,则ZXNavDefalutItemSize无效,若要恢复初始值,可设置为-1 32 | @property (assign, nonatomic)CGFloat zx_fixHeight; 33 | ///设置NavItemBtn距离左边元素的固定距离,若要恢复初始值,可设置为-1 34 | @property (assign, nonatomic)CGFloat zx_fixMarginLeft; 35 | ///设置NavItemBtn距离右边元素的固定距离,若要恢复初始值,可设置为-1 36 | @property (assign, nonatomic)CGFloat zx_fixMarginRight; 37 | ///设置NavItemBtn image的固定大小,若要恢复初始值,可设置为CGSizeZero 38 | @property (assign, nonatomic)CGSize zx_fixImageSize; 39 | ///设置NavItemBtn文字自动计算宽度后的附加宽度 40 | @property (assign, nonatomic)CGFloat zx_textAttachWidth; 41 | ///设置NavItemBtn文字的附加高度 42 | @property (assign, nonatomic)CGFloat zx_textAttachHeight; 43 | ///设置NavItemBtn的cornerRadius为高度的一半(圆形圆角) 44 | @property (assign, nonatomic)BOOL zx_setCornerRadiusRounded; 45 | ///设置NavItemBtn内部图片x轴的偏移量,负数代表左移,无title且设置了zx_fixImageSize后生效,仅改变内容imageView的位移,不会改变原始NavItemBtn的frame 46 | @property (assign, nonatomic)CGFloat zx_imageOffsetX; 47 | ///设置NavItemBtn的自定义view 48 | @property (strong, nonatomic, nullable)UIView *zx_customView; 49 | ///NavItemBtn frame发生改变时的回调,可在这个block中return修改后的frame 50 | @property(copy, nonatomic)CGRect(^zx_handleFrameBlock)(CGRect oldFrame); 51 | ///开始点击的回调 52 | @property (copy, nonatomic) void (^zx_touchesBeganBlock)(void); 53 | ///结束点击的回调 54 | @property (copy, nonatomic) void (^zx_touchesEndBlock)(void); 55 | ///手动更新布局,一般内部会自动调用,用于高度定制时无法自动更新布局时调用 56 | - (void)zx_updateLayout; 57 | ///刷新NavItemBtn的image和title布局,一般内部会自动调用 58 | - (void)zx_layoutImageAndTitle; 59 | @end 60 | 61 | NS_ASSUME_NONNULL_END 62 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavItemBtn.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavItemBtn.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | 12 | NS_ASSUME_NONNULL_BEGIN 13 | 14 | @interface ZXNavItemBtn : UIButton 15 | ///是否禁止设置title和attributedTitle 16 | @property (assign, nonatomic, readonly)BOOL zx_disableSetTitle; 17 | ///NavItemBtn的frame更新回调 18 | @property (copy, nonatomic) void (^zx_barItemBtnFrameUpdateBlock)(ZXNavItemBtn *barItemBtn); 19 | ///设置NavItemBtn的image颜色 20 | @property (strong, nonatomic, nullable)UIColor *zx_imageColor; 21 | ///设置NavItemBtn的tintColor 22 | @property (strong, nonatomic, nullable)UIColor *zx_tintColor; 23 | ///设置NavItemBtn的tintColor仅用于UIControlStateNormal状态(请在zx_imageColor和zx_tintColor之前设置),默认为NO 24 | @property (assign, nonatomic)UIColor *zx_useTintColorOnlyInStateNormal; 25 | ///设置NavItemBtn的字体大小 26 | @property (assign, nonatomic)CGFloat zx_fontSize; 27 | ///禁止自动调整按钮图片和文字的布局,若要使contentEdgeInsets、titleEdgeInsets、imageEdgeInsets等,则需要将此属性设置为NO 28 | @property (assign, nonatomic)BOOL zx_disableAutoLayoutImageAndTitle; 29 | ///设置NavItemBtn的固定宽度,若设置,则自动计算宽度无效,若要恢复初始值,可设置为-1 30 | @property (assign, nonatomic)CGFloat zx_fixWidth; 31 | ///设置NavItemBtn的固定高度,若设置,则ZXNavDefalutItemSize无效,若要恢复初始值,可设置为-1 32 | @property (assign, nonatomic)CGFloat zx_fixHeight; 33 | ///设置NavItemBtn距离左边元素的固定距离,若要恢复初始值,可设置为-1 34 | @property (assign, nonatomic)CGFloat zx_fixMarginLeft; 35 | ///设置NavItemBtn距离右边元素的固定距离,若要恢复初始值,可设置为-1 36 | @property (assign, nonatomic)CGFloat zx_fixMarginRight; 37 | ///设置NavItemBtn image的固定大小,若要恢复初始值,可设置为CGSizeZero 38 | @property (assign, nonatomic)CGSize zx_fixImageSize; 39 | ///设置NavItemBtn文字自动计算宽度后的附加宽度 40 | @property (assign, nonatomic)CGFloat zx_textAttachWidth; 41 | ///设置NavItemBtn文字的附加高度 42 | @property (assign, nonatomic)CGFloat zx_textAttachHeight; 43 | ///设置NavItemBtn的cornerRadius为高度的一半(圆形圆角) 44 | @property (assign, nonatomic)BOOL zx_setCornerRadiusRounded; 45 | ///设置NavItemBtn内部图片x轴的偏移量,负数代表左移,无title且设置了zx_fixImageSize后生效,仅改变内容imageView的位移,不会改变原始NavItemBtn的frame 46 | @property (assign, nonatomic)CGFloat zx_imageOffsetX; 47 | ///设置NavItemBtn的自定义view 48 | @property (strong, nonatomic, nullable)UIView *zx_customView; 49 | ///NavItemBtn frame发生改变时的回调,可在这个block中return修改后的frame 50 | @property(copy, nonatomic)CGRect(^zx_handleFrameBlock)(CGRect oldFrame); 51 | ///开始点击的回调 52 | @property (copy, nonatomic) void (^zx_touchesBeganBlock)(void); 53 | ///结束点击的回调 54 | @property (copy, nonatomic) void (^zx_touchesEndBlock)(void); 55 | ///手动更新布局,一般内部会自动调用,用于高度定制时无法自动更新布局时调用 56 | - (void)zx_updateLayout; 57 | ///刷新NavItemBtn的image和title布局,一般内部会自动调用 58 | - (void)zx_layoutImageAndTitle; 59 | @end 60 | 61 | NS_ASSUME_NONNULL_END 62 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoFoldXibViewController/DemoFoldXibViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoFoldXibViewController/DemoFoldXibViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoFoldXibViewController.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/13. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoFoldXibViewController.h" 10 | 11 | @interface DemoFoldXibViewController () 12 | @property (weak, nonatomic) IBOutlet UITableView *tableView; 13 | @property (strong, nonatomic) NSArray *datas; 14 | @property (assign, nonatomic) CGFloat lastOffsetY; 15 | 16 | @end 17 | 18 | @implementation DemoFoldXibViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | [self setUpNav]; 23 | [self setUpViewAndData]; 24 | } 25 | 26 | - (void)setUpNav{ 27 | self.title = @"可伸缩式导航栏"; 28 | self.zx_navStatusBarStyle = ZXNavStatusBarStyleLight; 29 | [self.zx_navLeftBtn setTitle:@"首页" forState:UIControlStateNormal]; 30 | self.zx_navBar.backgroundColor = [UIColor colorWithRed:16/255.0 green:94/255.0 blue:253/255.0 alpha:1]; 31 | self.zx_navTintColor = [UIColor whiteColor]; 32 | [self zx_setRightBtnWithImgName:@"recycle_icon" clickedBlock:nil]; 33 | } 34 | 35 | - (void)setUpViewAndData{ 36 | self.view.backgroundColor = [UIColor whiteColor]; 37 | self.datas = @[@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳"]; 38 | self.tableView.delegate = self; 39 | self.tableView.dataSource = self; 40 | } 41 | #pragma mark - UITableViewDataSource & UITableViewDelegate 42 | - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 43 | return self.datas.count; 44 | } 45 | 46 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 47 | UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; 48 | cell.textLabel.text = self.datas[indexPath.row]; 49 | return cell; 50 | } 51 | 52 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 53 | return 50; 54 | } 55 | 56 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 57 | [tableView deselectRowAtIndexPath:indexPath animated:NO]; 58 | } 59 | 60 | #pragma mark - UIScrollViewDelegate 61 | 62 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ 63 | 64 | CGFloat offsetY = scrollView.contentOffset.y; 65 | CGFloat distanceFromBottom = scrollView.contentSize.height - offsetY; 66 | CGFloat distance = offsetY - self.lastOffsetY; 67 | self.lastOffsetY = offsetY; 68 | if (distance > 0 && offsetY > 0) { 69 | //向上滚动,导航栏折叠 70 | if(!self.zx_navIsFolded){ 71 | //如果没有折叠 就折叠 72 | [self setNavFold:YES]; 73 | } 74 | 75 | } 76 | if (distance < 0 && distanceFromBottom > scrollView.zx_height) { 77 | //向下滚动 78 | if(self.zx_navIsFolded){ 79 | //如果有折叠 就展开 80 | [self setNavFold:NO]; 81 | } 82 | 83 | } 84 | } 85 | 86 | - (void)setNavFold:(BOOL)shouldFold{ 87 | [self zx_setNavFolded:shouldFold speed:3 foldingOffsetBlock:nil foldCompletionBlock:nil]; 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBar.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBar.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import "ZXNavigationBarDefine.h" 12 | #import "UIImage+ZXNavColorRender.h" 13 | #import "UIView+ZXNavFrameExtension.h" 14 | #import "NSString+ZXNavCalcSizeExtension.h" 15 | #import "NSAttributedString+ZXNavCalcSizeExtension.h" 16 | #import "ZXNavTitleLabel.h" 17 | #import "ZXNavItemBtn.h" 18 | #import "ZXNavBacImageView.h" 19 | #import "ZXNavTitleView.h" 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | @interface ZXNavigationBar : UIView 23 | /** 24 | 设置左右Button的大小(宽高相等) 25 | */ 26 | @property (assign, nonatomic)CGFloat zx_itemSize; 27 | /** 28 | 设置Item之间的间距 29 | */ 30 | @property (assign, nonatomic)CGFloat zx_itemMargin; 31 | /** 32 | 最左侧Button 33 | */ 34 | @property (weak, nonatomic)ZXNavItemBtn *zx_leftBtn; 35 | /** 36 | 左侧第二个Button 37 | */ 38 | @property (weak, nonatomic)ZXNavItemBtn *zx_subLeftBtn; 39 | /** 40 | 最右侧Button 41 | */ 42 | @property (weak, nonatomic)ZXNavItemBtn *zx_rightBtn; 43 | /** 44 | 右侧第二个Button 45 | */ 46 | @property (weak, nonatomic)ZXNavItemBtn *zx_subRightBtn; 47 | /** 48 | titleView,显示在正中间的标题View 49 | */ 50 | @property (weak, nonatomic, readonly)ZXNavTitleView *zx_titleView; 51 | /** 52 | titleLabel,显示在正中间的标题Label 53 | */ 54 | @property (weak, nonatomic)ZXNavTitleLabel *zx_titleLabel; 55 | /** 56 | 导航栏背景ImageView 57 | */ 58 | @property (weak, nonatomic)ZXNavBacImageView *zx_bacImageView; 59 | /** 60 | 导航栏背景渐变的CAGradientLayer 61 | */ 62 | @property (weak, nonatomic, nullable)CAGradientLayer *zx_gradientLayer; 63 | /** 64 | 导航栏背景图片 65 | */ 66 | @property (strong, nonatomic ,nullable)UIImage *zx_bacImage; 67 | /** 68 | 是否开启系统导航栏与自定义导航栏平滑过渡(务必仅当存在系统导航栏与自定义导航栏过渡时启用,非必要请勿启用,否则可能造成自定义导航栏跳动,若当前控制器显示了系统导航栏,请于当前控制器pop的上一个控制器中使用self.zx_navEnableSmoothFromSystemNavBar = YES) 69 | */ 70 | @property (assign, nonatomic, readonly)BOOL zx_navEnableSmoothFromSystemNavBar; 71 | /** 72 | 自定义的titleView,是TitleView的SubView 73 | */ 74 | @property (weak, nonatomic)UIView *zx_customTitleView; 75 | /** 76 | 自定义的导航栏View,是ZXNavigationBar的SubView 77 | */ 78 | @property (weak, nonatomic)UIView *zx_customNavBar; 79 | /** 80 | 分割线 81 | */ 82 | @property (weak, nonatomic)UIView *lineView ZXNavigationBarDeprecated("从版本1.3.6起,此属性过期,请使用zx_lineView"); 83 | /** 84 | 分割线 85 | */ 86 | @property (weak, nonatomic)UIView *zx_lineView; 87 | /** 88 | 分割线的高度,默认为1 89 | */ 90 | @property (assign, nonatomic)CGFloat zx_lineViewHeight; 91 | /** 92 | 最左侧Button点击回调 93 | */ 94 | @property (copy, nonatomic) void (^zx_leftBtnClickedBlock)(ZXNavItemBtn *btn); 95 | /** 96 | 左侧第二个Button点击回调 97 | */ 98 | @property (copy, nonatomic) void (^zx_subLeftBtnClickedBlock)(ZXNavItemBtn *btn); 99 | /** 100 | 最右侧Button点击回调 101 | */ 102 | @property (copy, nonatomic) void (^zx_rightBtnClickedBlock)(ZXNavItemBtn *btn); 103 | /** 104 | 右侧第二个Button点击回调 105 | */ 106 | @property (copy, nonatomic) void (^zx_subRightBtnClickedBlock)(ZXNavItemBtn *btn); 107 | 108 | /** 109 | 导航栏背景色Components 110 | */ 111 | @property (strong, nonatomic, readonly) NSArray* zx_backgroundColorComponents; 112 | /** 113 | 设置大小标题效果 114 | 115 | @param title 大标题 116 | @param subTitle 小标题 117 | */ 118 | - (void)zx_setMultiTitle:(NSString *)title subTitle:(NSString *)subTitle; 119 | 120 | /** 121 | 设置大小标题效果 122 | 123 | @param title 大标题 124 | @param subTitle 小标题 125 | @param subTitleFont 小标题字体 126 | @param subTitleColor 小标题颜色 127 | */ 128 | - (void)zx_setMultiTitle:(NSString *)title subTitle:(NSString *)subTitle subTitleFont:(UIFont *)subTitleFont subTitleTextColor:(UIColor *)subTitleColor; 129 | 130 | @end 131 | 132 | NS_ASSUME_NONNULL_END 133 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBar.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBar.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import 11 | #import "ZXNavigationBarDefine.h" 12 | #import "UIImage+ZXNavColorRender.h" 13 | #import "UIView+ZXNavFrameExtension.h" 14 | #import "NSString+ZXNavCalcSizeExtension.h" 15 | #import "NSAttributedString+ZXNavCalcSizeExtension.h" 16 | #import "ZXNavTitleLabel.h" 17 | #import "ZXNavItemBtn.h" 18 | #import "ZXNavBacImageView.h" 19 | #import "ZXNavTitleView.h" 20 | NS_ASSUME_NONNULL_BEGIN 21 | 22 | @interface ZXNavigationBar : UIView 23 | /** 24 | 设置左右Button的大小(宽高相等) 25 | */ 26 | @property (assign, nonatomic)CGFloat zx_itemSize; 27 | /** 28 | 设置Item之间的间距 29 | */ 30 | @property (assign, nonatomic)CGFloat zx_itemMargin; 31 | /** 32 | 最左侧Button 33 | */ 34 | @property (weak, nonatomic)ZXNavItemBtn *zx_leftBtn; 35 | /** 36 | 左侧第二个Button 37 | */ 38 | @property (weak, nonatomic)ZXNavItemBtn *zx_subLeftBtn; 39 | /** 40 | 最右侧Button 41 | */ 42 | @property (weak, nonatomic)ZXNavItemBtn *zx_rightBtn; 43 | /** 44 | 右侧第二个Button 45 | */ 46 | @property (weak, nonatomic)ZXNavItemBtn *zx_subRightBtn; 47 | /** 48 | titleView,显示在正中间的标题View 49 | */ 50 | @property (weak, nonatomic, readonly)ZXNavTitleView *zx_titleView; 51 | /** 52 | titleLabel,显示在正中间的标题Label 53 | */ 54 | @property (weak, nonatomic)ZXNavTitleLabel *zx_titleLabel; 55 | /** 56 | 导航栏背景ImageView 57 | */ 58 | @property (weak, nonatomic)ZXNavBacImageView *zx_bacImageView; 59 | /** 60 | 导航栏背景渐变的CAGradientLayer 61 | */ 62 | @property (weak, nonatomic, nullable)CAGradientLayer *zx_gradientLayer; 63 | /** 64 | 导航栏背景图片 65 | */ 66 | @property (strong, nonatomic ,nullable)UIImage *zx_bacImage; 67 | /** 68 | 是否开启系统导航栏与自定义导航栏平滑过渡(务必仅当存在系统导航栏与自定义导航栏过渡时启用,非必要请勿启用,否则可能造成自定义导航栏跳动,若当前控制器显示了系统导航栏,请于当前控制器pop的上一个控制器中使用self.zx_navEnableSmoothFromSystemNavBar = YES) 69 | */ 70 | @property (assign, nonatomic, readonly)BOOL zx_navEnableSmoothFromSystemNavBar; 71 | /** 72 | 自定义的titleView,是TitleView的SubView 73 | */ 74 | @property (weak, nonatomic)UIView *zx_customTitleView; 75 | /** 76 | 自定义的导航栏View,是ZXNavigationBar的SubView 77 | */ 78 | @property (weak, nonatomic)UIView *zx_customNavBar; 79 | /** 80 | 分割线 81 | */ 82 | @property (weak, nonatomic)UIView *lineView ZXNavigationBarDeprecated("从版本1.3.6起,此属性过期,请使用zx_lineView"); 83 | /** 84 | 分割线 85 | */ 86 | @property (weak, nonatomic)UIView *zx_lineView; 87 | /** 88 | 分割线的高度,默认为1 89 | */ 90 | @property (assign, nonatomic)CGFloat zx_lineViewHeight; 91 | /** 92 | 最左侧Button点击回调 93 | */ 94 | @property (copy, nonatomic) void (^zx_leftBtnClickedBlock)(ZXNavItemBtn *btn); 95 | /** 96 | 左侧第二个Button点击回调 97 | */ 98 | @property (copy, nonatomic) void (^zx_subLeftBtnClickedBlock)(ZXNavItemBtn *btn); 99 | /** 100 | 最右侧Button点击回调 101 | */ 102 | @property (copy, nonatomic) void (^zx_rightBtnClickedBlock)(ZXNavItemBtn *btn); 103 | /** 104 | 右侧第二个Button点击回调 105 | */ 106 | @property (copy, nonatomic) void (^zx_subRightBtnClickedBlock)(ZXNavItemBtn *btn); 107 | 108 | /** 109 | 导航栏背景色Components 110 | */ 111 | @property (strong, nonatomic, readonly) NSArray* zx_backgroundColorComponents; 112 | /** 113 | 设置大小标题效果 114 | 115 | @param title 大标题 116 | @param subTitle 小标题 117 | */ 118 | - (void)zx_setMultiTitle:(NSString *)title subTitle:(NSString *)subTitle; 119 | 120 | /** 121 | 设置大小标题效果 122 | 123 | @param title 大标题 124 | @param subTitle 小标题 125 | @param subTitleFont 小标题字体 126 | @param subTitleColor 小标题颜色 127 | */ 128 | - (void)zx_setMultiTitle:(NSString *)title subTitle:(NSString *)subTitle subTitleFont:(UIFont *)subTitleFont subTitleTextColor:(UIColor *)subTitleColor; 129 | 130 | @end 131 | 132 | NS_ASSUME_NONNULL_END 133 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoFoldFrameViewController/DemoFoldFrameViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoTelescopicViewController.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/13. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoFoldFrameViewController.h" 10 | 11 | @interface DemoFoldFrameViewController () 12 | @property (strong, nonatomic) UITableView *tableView; 13 | @property (strong, nonatomic) NSArray *datas; 14 | @property (assign, nonatomic) CGFloat lastOffsetY; 15 | @end 16 | 17 | @implementation DemoFoldFrameViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | [self setUpNav]; 22 | [self setUpViewAndData]; 23 | } 24 | 25 | - (void)setUpNav{ 26 | self.title = @"可伸缩式导航栏(Frame)"; 27 | self.zx_navStatusBarStyle = ZXNavStatusBarStyleLight; 28 | [self.zx_navLeftBtn setTitle:@"首页" forState:UIControlStateNormal]; 29 | self.zx_navBar.backgroundColor = [UIColor colorWithRed:16/255.0 green:94/255.0 blue:253/255.0 alpha:1]; 30 | self.zx_navTintColor = [UIColor whiteColor]; 31 | [self zx_setRightBtnWithImgName:@"recycle_icon" clickedBlock:nil]; 32 | } 33 | 34 | - (void)setUpViewAndData{ 35 | self.view.backgroundColor = [UIColor whiteColor]; 36 | self.datas = @[@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳"]; 37 | self.tableView = [[UITableView alloc]init]; 38 | [self.view addSubview:self.tableView]; 39 | self.tableView.delegate = self; 40 | self.tableView.dataSource = self; 41 | self.tableView.frame = CGRectMake(0, ZXNavBarHeight, self.view.frame.size.width, self.view.frame.size.height - ZXNavBarHeight); 42 | } 43 | 44 | #pragma mark - UITableViewDataSource & UITableViewDelegate 45 | - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 46 | return self.datas.count; 47 | } 48 | 49 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 50 | UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; 51 | cell.textLabel.text = self.datas[indexPath.row]; 52 | return cell; 53 | } 54 | 55 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 56 | return 50; 57 | } 58 | 59 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 60 | [tableView deselectRowAtIndexPath:indexPath animated:NO]; 61 | } 62 | 63 | #pragma mark - UIScrollViewDelegate 64 | 65 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ 66 | 67 | CGFloat offsetY = scrollView.contentOffset.y; 68 | CGFloat distanceFromBottom = scrollView.contentSize.height - offsetY; 69 | CGFloat distance = offsetY - self.lastOffsetY; 70 | self.lastOffsetY = offsetY; 71 | if (distance > 0 && offsetY > 0) { 72 | //向上滚动,导航栏折叠 73 | if(!self.zx_navIsFolded){ 74 | //如果没有折叠 就折叠 75 | [self setNavFold:YES]; 76 | } 77 | 78 | } 79 | if (distance < 0 && distanceFromBottom > scrollView.zx_height) { 80 | //向下滚动 81 | if(self.zx_navIsFolded){ 82 | //如果有折叠 就展开 83 | [self setNavFold:NO]; 84 | } 85 | 86 | } 87 | } 88 | 89 | - (void)setNavFold:(BOOL)shouldFold{ 90 | __weak typeof(self) weakSelf = self; 91 | [self zx_setNavFolded:shouldFold speed:3 foldingOffsetBlock:^(CGFloat offset) { 92 | //tableView的y值跟随导航栏变化(导航栏高度减小,tableView的y值减小) 93 | weakSelf.tableView.zx_y += offset; 94 | //tableView的高度值跟随这导航栏变化(导航栏高度减小,tableView高度增加) 95 | weakSelf.tableView.zx_height -= offset; 96 | } foldCompletionBlock:nil]; 97 | } 98 | @end 99 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCompatibleScrollViewViewController/DemoCompatibleScrollViewViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCompatibleScrollViewViewController.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/7/29. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoCompatibleScrollViewViewController.h" 10 | #define random(r, g, b, a) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:(a)/255.0] 11 | #define randomColor random(arc4random_uniform(200), arc4random_uniform(200), arc4random_uniform(200), 255.0) 12 | 13 | @interface DemoCompatibleScrollViewViewController () 14 | @property (strong, nonatomic) UIScrollView *scrollView; 15 | @property (strong, nonatomic) UIScrollView *topScrollView; 16 | @end 17 | 18 | @implementation DemoCompatibleScrollViewViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | [self setUpNav]; 23 | [self setUpView]; 24 | 25 | } 26 | 27 | - (void)setUpNav{ 28 | [self zx_setMultiTitle:self.title subTitle:@"兼容设置多ScrollView与侧滑返回手势演示"]; 29 | //加这一行代码即可解决ScrollView与侧滑返回手势冲突问题(这里演示同时兼容两个scrollView的情况) 30 | [self zx_setPopGestureCompatibleScrollViews:@[self.topScrollView,self.scrollView]]; 31 | //当导航控制器为ZXNavigationBarNavigationController或继承于ZXNavigationBarNavigationController时,如果需要更复杂的定制化的情况,可以使用下方的方式,以下代码的作用是在scrollView滚动到第一页的时候,支持pop手势多层级同时触发,为了更好的展示效果,建议关闭scrollView的bounces 32 | 33 | /* 34 | self.scrollView.bounces = NO; 35 | __weak typeof(self) weakSelf = self; 36 | self.zx_popGestureShouldRecognizeSimultaneously = ^BOOL(UIGestureRecognizer * _Nonnull otherGestureRecognizer) { 37 | if(weakSelf.scrollView.contentOffset.x <= 0){ 38 | return YES; 39 | } 40 | return NO; 41 | }; 42 | */ 43 | } 44 | 45 | 46 | - (void)setUpView{ 47 | self.view.backgroundColor = [UIColor whiteColor]; 48 | [self.view addSubview:self.topScrollView]; 49 | [self.view addSubview:self.scrollView]; 50 | [self setUpScrollViewData]; 51 | } 52 | 53 | - (void)setUpScrollViewData{ 54 | [self layoutScrollViewSubviews:self.topScrollView]; 55 | [self layoutScrollViewSubviews:self.scrollView]; 56 | } 57 | 58 | - (void)layoutScrollViewSubviews:(UIScrollView *)scrollView{ 59 | scrollView.pagingEnabled = YES; 60 | UIView *lastView; 61 | [scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 62 | for(int i = 0; i < 10; i++){ 63 | UIView *view = [[UIView alloc]init]; 64 | view.backgroundColor = randomColor; 65 | view.frame = CGRectMake(i * scrollView.zx_width, 0, scrollView.zx_width, scrollView.zx_height); 66 | UILabel *titleLabel = [[UILabel alloc]init]; 67 | titleLabel.frame = view.bounds; 68 | titleLabel.font = [UIFont boldSystemFontOfSize:70]; 69 | titleLabel.textAlignment = NSTextAlignmentCenter; 70 | titleLabel.textColor = [UIColor whiteColor]; 71 | titleLabel.text = [NSString stringWithFormat:@"%d",i + 1]; 72 | [view addSubview:titleLabel]; 73 | [scrollView addSubview:view]; 74 | lastView = view; 75 | } 76 | if(lastView){ 77 | [scrollView setContentSize:CGSizeMake(CGRectGetMaxX(lastView.frame), 0)]; 78 | } 79 | [scrollView setContentOffset:CGPointZero]; 80 | } 81 | 82 | - (void)viewDidLayoutSubviews{ 83 | [super viewDidLayoutSubviews]; 84 | self.topScrollView.frame = CGRectMake(0, ZXNavBarHeight, self.view.zx_width, 200); 85 | self.scrollView.frame = CGRectMake(0, ZXNavBarHeight + 200, self.view.zx_width, self.view.zx_height - ZXNavBarHeight - 200); 86 | [self setUpScrollViewData]; 87 | } 88 | 89 | 90 | - (UIScrollView *)scrollView{ 91 | if(!_scrollView){ 92 | _scrollView = [[UIScrollView alloc]init]; 93 | [self.view addSubview:_scrollView]; 94 | } 95 | return _scrollView; 96 | } 97 | 98 | - (UIScrollView *)topScrollView{ 99 | if(!_topScrollView){ 100 | _topScrollView = [[UIScrollView alloc]init]; 101 | [self.view addSubview:_topScrollView]; 102 | } 103 | return _topScrollView; 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoXibViewController/DemoXibViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoXibViewController.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoXibViewController.h" 10 | #import "DemoSystemBarViewController.h" 11 | @interface DemoXibViewController () 12 | ///是否禁止pop操作 13 | @property(assign, nonatomic)BOOL disablePop; 14 | @end 15 | 16 | @implementation DemoXibViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | //设置导航栏标题 22 | self.title = @"ZXNavigationBar"; 23 | 24 | //设置最右侧的Button的图片和点击回调 25 | [self zx_setRightBtnWithImgName:@"set_icon" clickedBlock:^(UIButton * _Nonnull btn) { 26 | NSLog(@"点击了最右侧的Button"); 27 | }]; 28 | 29 | //最左侧的按钮添加”返回“文字,当当前控制器不是第0个的时候,ZXNavigationBar会自动显示返回图片,且点击返回上一个控制器 30 | [self.zx_navLeftBtn setTitle:@"返回" forState:UIControlStateNormal]; 31 | 32 | __weak typeof(self) weakSelf = self; 33 | self.zx_handlePopBlock = ^BOOL(ZXNavigationBarController * _Nonnull viewController, ZXNavPopBlockFrom popBlockFrom) { 34 | return !weakSelf.disablePop; 35 | }; 36 | } 37 | 38 | #pragma mark - Actions 39 | 40 | #pragma mark 点击了设置背景色橙色 41 | - (IBAction)changeBacColorAction:(UISwitch *)sender { 42 | if(sender.on){ 43 | self.zx_navBarBackgroundColor = [UIColor orangeColor]; 44 | }else{ 45 | self.zx_navBarBackgroundColor = [UIColor whiteColor]; 46 | } 47 | } 48 | 49 | #pragma mark 点击了设置背景图片 50 | - (IBAction)setBacImageAction:(UISwitch *)sender { 51 | if(sender.on){ 52 | self.zx_navBarBackgroundImage = [UIImage imageNamed:@"nav_bac"]; 53 | }else{ 54 | self.zx_navBarBackgroundImage = nil; 55 | } 56 | } 57 | 58 | #pragma mark 点击了设置TintColor黄色 59 | - (IBAction)ChangeTintColorAction:(UISwitch *)sender { 60 | if(sender.on){ 61 | self.zx_navTintColor = [UIColor yellowColor]; 62 | }else{ 63 | self.zx_navTintColor = [UIColor blackColor]; 64 | } 65 | } 66 | 67 | #pragma mark 点击了设置大小标题效果 68 | - (IBAction)setBigSubTitleAction:(UISwitch *)sender { 69 | if(sender.on){ 70 | [self zx_setMultiTitle:@"ZXNavigationBar" subTitle:@"subTitle"]; 71 | }else{ 72 | self.title = @"ZXNavigationBar"; 73 | } 74 | } 75 | 76 | #pragma mark 点击了设置StatusBar白色 77 | - (IBAction)changeStatusBarAction:(UISwitch *)sender { 78 | if(sender.on){ 79 | self.zx_navStatusBarStyle = ZXNavStatusBarStyleLight; 80 | }else{ 81 | self.zx_navStatusBarStyle = ZXNavStatusBarStyleDefault; 82 | } 83 | } 84 | 85 | #pragma mark 点击了设置两边Item大小为30 86 | - (IBAction)changeItemSizeAction:(UISwitch *)sender { 87 | if(sender.on){ 88 | self.zx_navItemSize = 30; 89 | }else{ 90 | self.zx_navItemSize = ZXNavDefalutItemSize; 91 | } 92 | } 93 | 94 | #pragma mark 点击了设置两边Item边距为0 95 | - (IBAction)changeItemMarginAction:(UISwitch *)sender { 96 | if(sender.on){ 97 | self.zx_navItemMargin = 0; 98 | }else{ 99 | self.zx_navItemMargin = ZXNavDefalutItemMargin; 100 | } 101 | } 102 | 103 | #pragma mark 点击了设置渐变背景 104 | - (IBAction)changeGradientBacAction:(UISwitch *)sender { 105 | if(sender.on){ 106 | [self zx_setNavGradientBacFrom:[UIColor magentaColor] to:[UIColor cyanColor]]; 107 | }else{ 108 | [self zx_removeNavGradientBac]; 109 | } 110 | 111 | } 112 | 113 | #pragma mark 点击了更换为系统的导航栏 114 | - (IBAction)changeSystemNavBarAction:(UISwitch *)sender { 115 | if(sender.on){ 116 | self.zx_showSystemNavBar = YES; 117 | }else{ 118 | self.zx_showSystemNavBar = NO; 119 | self.zx_hideBaseNavBar = NO; 120 | } 121 | 122 | } 123 | 124 | #pragma mark 点击了右侧显示两个Item 125 | - (IBAction)changeRightSubBtnAction:(UISwitch *)sender { 126 | if(sender.on){ 127 | //设置自定义NavItemView 128 | self.zx_navSubRightBtn.zx_customView = [UISwitch new]; 129 | }else{ 130 | self.zx_navSubRightBtn.zx_customView = nil; 131 | } 132 | } 133 | 134 | - (IBAction)disPopAction:(UISwitch *)sender { 135 | self.disablePop = sender.on; 136 | } 137 | 138 | @end 139 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoListViewController/DemoListViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoListViewController.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/10. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoListViewController.h" 10 | #import "DemoXibViewController.h" 11 | #import "DemoWeiboHotViewController.h" 12 | #import "DemoCustomNavViewController.h" 13 | #import "DemoCustomTitleViewViewController.h" 14 | #import "DemoSystemBarViewController.h" 15 | #import "DemoFoldFrameViewController.h" 16 | #import "DemoFoldXibViewController.h" 17 | #import "DemoCompatibleScrollViewViewController.h" 18 | #import "DemoPublicSystemBarViewController.h" 19 | @interface DemoListViewController () 20 | @property (strong, nonatomic) UITableView *tableView; 21 | @property (strong, nonatomic) NSArray *datas; 22 | @end 23 | 24 | @implementation DemoListViewController 25 | 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | [self setUpNav]; 29 | [self setUpViewAndData]; 30 | } 31 | 32 | - (void)setUpNav{ 33 | self.title = @"ZXNavigationBar"; 34 | self.zx_navEnableSmoothFromSystemNavBar = YES; 35 | } 36 | 37 | - (void)setUpViewAndData{ 38 | self.datas = @[@"ZXNavigationBar属性设置",@"仿微博热搜页面导航栏",@"可伸缩式导航栏(从Xib中设置tableView约束)",@"可伸缩式导航栏(通过Frame设置tableView约束)",@"自定义导航栏",@"自定义TitleView",@"跳转到使用系统导航栏的控制器",@"ScrollView与侧滑返回手势冲突处理"]; 39 | self.tableView = [[UITableView alloc]init]; 40 | [self.view addSubview:self.tableView]; 41 | self.tableView.delegate = self; 42 | self.tableView.dataSource = self; 43 | } 44 | 45 | 46 | - (void)viewDidLayoutSubviews{ 47 | [super viewDidLayoutSubviews]; 48 | self.tableView.frame = CGRectMake(0, ZXNavBarHeight, self.view.frame.size.width, self.view.frame.size.height - ZXNavBarHeight); 49 | } 50 | 51 | #pragma mark - UITableViewDataSource & UITableViewDelegate 52 | - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 53 | return self.datas.count; 54 | } 55 | 56 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 57 | UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; 58 | cell.textLabel.text = self.datas[indexPath.row]; 59 | return cell; 60 | } 61 | 62 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 63 | return 70; 64 | } 65 | 66 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 67 | [tableView deselectRowAtIndexPath:indexPath animated:NO]; 68 | UIViewController *vc; 69 | switch (indexPath.row) { 70 | case 0:{ 71 | //跳转到ZXNavigationBar属性设置 72 | vc = [[DemoXibViewController alloc]init]; 73 | break; 74 | } 75 | case 1:{ 76 | //仿微博热搜页面导航栏 77 | vc = [[DemoWeiboHotViewController alloc]init]; 78 | break; 79 | } 80 | case 2:{ 81 | //可伸缩式导航栏(从Xib中设置tableView约束) 82 | vc = [[DemoFoldXibViewController alloc]init]; 83 | break; 84 | } 85 | case 3:{ 86 | //可伸缩式导航栏(通过Frame设置tableView约束) 87 | vc = [[DemoFoldFrameViewController alloc]init]; 88 | break; 89 | } 90 | case 4:{ 91 | //自定义导航栏 92 | vc = [[DemoCustomNavViewController alloc]init]; 93 | break; 94 | } 95 | case 5:{ 96 | //自定义TitleView 97 | vc = [[DemoCustomTitleViewViewController alloc]init]; 98 | break; 99 | } 100 | case 6:{ 101 | //跳转到使用系统导航栏的控制器 102 | vc = [[DemoPublicSystemBarViewController alloc]init]; 103 | break; 104 | } 105 | case 7:{ 106 | //与ScrollView侧滑返回手势冲突处理 107 | vc = [[DemoCompatibleScrollViewViewController alloc]init]; 108 | break; 109 | } 110 | 111 | default: 112 | break; 113 | } 114 | if(vc){ 115 | vc.title = self.datas[indexPath.row]; 116 | [self.navigationController pushViewController:vc animated:YES]; 117 | } 118 | } 119 | 120 | 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoWeiboHotViewController/DemoWeiboHotViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoWeiboHotViewController.m 3 | // ZXNavigationBarDemo 4 | // 5 | // Created by 李兆祥 on 2020/3/12. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // 8 | 9 | #import "DemoWeiboHotViewController.h" 10 | #import "UIView+ZXNavFrameExtension.h" 11 | #import "DemoSystemBarViewController.h" 12 | @interface DemoWeiboHotViewController() 13 | @property (strong, nonatomic) UITableView *tableView; 14 | @property (strong, nonatomic) NSArray *datas; 15 | @end 16 | @implementation DemoWeiboHotViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | [self setUpNav]; 21 | [self setUpViewAndData]; 22 | } 23 | 24 | - (void)setUpNav{ 25 | //设置导航栏背景色RGB中Alpha为0 26 | self.zx_navBarBackgroundColorAlpha = 0; 27 | //左侧按钮添加”返回“文字 28 | [self.zx_navLeftBtn setTitle:@"返回" forState:UIControlStateNormal]; 29 | //设置最右侧按钮的图片和点击事件 30 | __weak typeof(self) weakSelf = self; 31 | [self zx_setRightBtnWithImgName:@"right_more_icon" clickedBlock:^(ZXNavItemBtn * _Nonnull btn) { 32 | NSLog(@"点击了最右边的按钮"); 33 | DemoSystemBarViewController *vc = [[DemoSystemBarViewController alloc]init]; 34 | [weakSelf.navigationController pushViewController:vc animated:YES]; 35 | }]; 36 | self.zx_navEnableSmoothFromSystemNavBar = YES; 37 | [self setLightNav]; 38 | } 39 | 40 | - (void)setUpViewAndData{ 41 | self.datas = @[@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳",@"武汉加油,中国加油🇨🇳"]; 42 | self.tableView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStyleGrouped]; 43 | [self.view addSubview:self.tableView]; 44 | self.tableView.delegate = self; 45 | self.tableView.dataSource = self; 46 | } 47 | 48 | - (void)viewDidLayoutSubviews{ 49 | [super viewDidLayoutSubviews]; 50 | self.tableView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); 51 | } 52 | 53 | #pragma mark 设置导航栏为黑色 54 | - (void)setDarkNav{ 55 | //设置导航栏文字标题和两侧按钮的颜色为黑色 56 | [self setZx_navTintColor:[UIColor blackColor]]; 57 | //设置导航栏文字标题 58 | self.title = @"微博热搜"; 59 | //隐藏分割线 60 | self.zx_navLineView.hidden = NO; 61 | //设置状态栏为黑色 62 | self.zx_navStatusBarStyle = ZXNavStatusBarStyleDefault; 63 | } 64 | 65 | #pragma mark 设置导航栏为白色 66 | - (void)setLightNav{ 67 | //设置导航栏文字标题和两侧按钮的颜色为白色 68 | [self setZx_navTintColor:[UIColor whiteColor]]; 69 | //设置导航栏文字标题 70 | self.title = @""; 71 | //显示分割线 72 | self.zx_navLineView.hidden = YES; 73 | //设置状态栏为白色 74 | self.zx_navStatusBarStyle = ZXNavStatusBarStyleLight; 75 | } 76 | 77 | #pragma mark - UIScrollViewDelegate 78 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ 79 | [self zx_setNavTransparentGradientsWithScrollView:scrollView fullChangeHeight:100 changeLimitNavAlphe:0.7 transparentGradientsTransparentBlock:^{ 80 | [self setLightNav]; 81 | } transparentGradientsOpaqueBlock:^{ 82 | [self setDarkNav]; 83 | }]; 84 | } 85 | 86 | 87 | #pragma mark - UITableViewDataSource & UITableViewDelegate 88 | - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 89 | return self.datas.count; 90 | } 91 | 92 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 93 | UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; 94 | cell.textLabel.text = self.datas[indexPath.row]; 95 | return cell; 96 | } 97 | 98 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 99 | return 50; 100 | } 101 | 102 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 103 | [tableView deselectRowAtIndexPath:indexPath animated:NO]; 104 | } 105 | 106 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ 107 | UIImageView *headerImageView = [[UIImageView alloc]init]; 108 | headerImageView.image = [UIImage imageNamed:@"weibo_hot_bac.jpg"]; 109 | return headerImageView; 110 | } 111 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ 112 | return self.view.frame.size.width * 0.5; 113 | } 114 | @end 115 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCustomTitleViewViewController/DemoCustomTitleView/DemoCustomTitleView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarDefine.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBarDefine.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #ifndef ZXNavigationBarDefine_h 11 | #define ZXNavigationBarDefine_h 12 | #define ZXNavDefalutBacColor [UIColor whiteColor] 13 | #define ZXNavDefalutTitleColor [UIColor blackColor] 14 | #define ZXNavDefalutLineColor [UIColor colorWithRed:220 / 255.0 green:220 / 255.0 blue:220 / 255.0 alpha:0.8] 15 | #define ZXNavDefalutItemTextColor [UIColor blackColor] 16 | 17 | #define ZXNavDefalutTitleSize 17 18 | #define ZXNavDefalutSubTitleSize 10 19 | #define ZXNavDefalutItemFontSize 15 20 | 21 | #define ZXNavDefalutItemSize 22 22 | #define ZXNavDefalutItemMargin 10 23 | 24 | #define ZXNavHistoryStackCellHeight 44 25 | #define ZXNavHistoryStackCellTitleX 16 26 | #define ZXNavHistoryStackViewWidth 250 27 | #define ZXNavHistoryStackViewItemMaxLength 6 28 | #define ZXNavHistoryStackViewStyleDarkBackgroundColor [UIColor colorWithRed:16 / 255.0 green:16 / 255.0 blue:16 / 255.0 alpha:1] 29 | #define ZXNavHistoryStackViewStyleDarkSelectedColor [UIColor colorWithRed:66 / 255.0 green:66 / 255.0 blue:66 / 255.0 alpha:1] 30 | #define ZXNavHistoryStackViewStyleLightBackgroundColor [UIColor colorWithRed:255.0 / 255.0 green:255.0 / 255.0 blue:255.0 / 255.0 alpha:1] 31 | #define ZXNavHistoryStackViewStyleLightSelectedColor [UIColor colorWithRed:225 / 255.0 green:225 / 255.0 blue:225 / 255.0 alpha:1] 32 | 33 | /** 34 | 获取主Window 35 | 36 | @return 主Window 37 | */ 38 | #define ZXMainWindow ([UIApplication sharedApplication].keyWindow ?: [UIApplication sharedApplication].windows.firstObject) 39 | 40 | /** 41 | 获取是否是iPad设备 42 | 43 | @return 是否是iPad设备 44 | */ 45 | #define ZXIsIPad ([[UIDevice currentDevice] userInterfaceIdiom]==UIUserInterfaceIdiomPad) 46 | 47 | /** 48 | 判断是否是刘海屏(全面屏iPad不算) 49 | 50 | @return 是否是刘海屏(全面屏iPad不算) 51 | */ 52 | #define ZXIsBangScreen ({\ 53 | int cFlag = 0;\ 54 | if(ZXIsIPad){cFlag = 0;}\ 55 | else if(@available(iOS 11.0, *)){\ 56 | if(ZXMainWindow.safeAreaInsets.bottom > 0){\ 57 | cFlag = 1;\ 58 | }else{\ 59 | cFlag = 0;\ 60 | }\ 61 | }else{\ 62 | cFlag = 0;\ 63 | }\ 64 | cFlag;\ 65 | }) 66 | 67 | /** 68 | 是否是全面屏iPad 69 | 70 | @return 是否是全面屏iPad 71 | */ 72 | #define ZXIsFullScreenIpad ({\ 73 | int cFlag = 0;\ 74 | if(@available(iOS 11.0, *)){\ 75 | if(ZXMainWindow.safeAreaInsets.bottom > 0 && ZXIsIPad){\ 76 | cFlag = 1;\ 77 | }else{\ 78 | cFlag = 0;\ 79 | }\ 80 | }else{\ 81 | cFlag = 0;\ 82 | }\ 83 | cFlag;\ 84 | }) 85 | 86 | /** 87 | 判断手机是否是横屏 88 | 89 | @return 手机是否是横屏 90 | */ 91 | #define ZXIsHorizontalScreen ([UIApplication sharedApplication].statusBarOrientation == UIDeviceOrientationLandscapeRight || [UIApplication sharedApplication].statusBarOrientation == UIDeviceOrientationLandscapeLeft) 92 | 93 | /** 94 | 获取屏幕宽度 95 | 96 | @return 屏幕宽度 97 | */ 98 | #define ZXScreenWidth [UIScreen mainScreen].bounds.size.width 99 | 100 | /** 101 | 获取屏幕高度 102 | 103 | @return 屏幕高度 104 | */ 105 | #define ZXScreenHeight [UIScreen mainScreen].bounds.size.height 106 | 107 | /** 108 | 获取导航栏高度(不包含状态栏高度) 109 | 110 | @return 导航栏高度(不包含状态栏高度) 111 | */ 112 | #define ZXNavBarHeightNotIncludeStatusBar (ZXIsIPad ? 50 : 44) 113 | 114 | 115 | /** 116 | 获取iPhone设备状态栏高度 117 | 118 | @return iPhone设备状态栏高度 119 | */ 120 | #define ZXIPhoneAppStatusBarHeight ({\ 121 | int height = 0;\ 122 | if(@available(iOS 13.0, *)){\ 123 | height = [[UIApplication sharedApplication] statusBarFrame].size.height != 0 ? [[UIApplication sharedApplication] statusBarFrame].size.height : (ZXIsBangScreen ? 44 : 20);\ 124 | }else{\ 125 | height = (ZXIsBangScreen ? 44 : 20);\ 126 | }\ 127 | height;\ 128 | }) 129 | 130 | /** 131 | 获取状态栏高度 132 | 133 | @return 状态栏高度 134 | */ 135 | //#define ZXAppStatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height 136 | //适配iOS13以下系统开启热点或音视频时的导航栏(因为iOS13以下系统开启或音视频时状态栏会增高,从而导致计算出来的整个导航栏增高) 137 | #define ZXAppStatusBarHeight (ZXIsHorizontalScreen ? ZXRealAppStatusBarHeight : ZXIsFullScreenIpad ? ZXRealAppStatusBarHeight : ZXIPhoneAppStatusBarHeight) 138 | 139 | 140 | /** 141 | 获取真实状态栏高度 142 | 143 | @return 真实状态栏高度 144 | */ 145 | #define ZXRealAppStatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height 146 | 147 | /** 148 | 获取导航栏高度 149 | 150 | @return 导航栏高度 151 | */ 152 | #define ZXNavBarHeight (ZXAppStatusBarHeight + ZXNavBarHeightNotIncludeStatusBar) 153 | 154 | /** 155 | 获取安全区域顶部高度 156 | 157 | @return 安全区域顶部高度 158 | */ 159 | #define ZXSafeAreaTop ({\ 160 | int height = 0;\ 161 | if (@available(iOS 11.0, *)) {\ 162 | height = ZXMainWindow.safeAreaInsets.top;\ 163 | }else{\ 164 | height = 0;\ 165 | }\ 166 | height;\ 167 | }) 168 | 169 | /** 170 | 获取安全区域底部高度 171 | 172 | @return 安全区域底部高度 173 | */ 174 | #define ZXSafeAreaBottom ({\ 175 | int height = 0;\ 176 | if (@available(iOS 11.0, *)) {\ 177 | height = ZXMainWindow.safeAreaInsets.bottom;\ 178 | }else{\ 179 | height = 0;\ 180 | }\ 181 | height;\ 182 | }) 183 | 184 | /** 185 | 获取横屏后左右安全距离 186 | 187 | @return 横屏后左右安全距离 188 | */ 189 | #define ZXHorizontaledSafeArea ((ZXIsHorizontalScreen && ZXIsBangScreen)? ZXNavBarHeightNotIncludeStatusBar : 0) 190 | 191 | /** 192 | 属性过期标注 193 | */ 194 | #define ZXNavigationBarDeprecated(DESCRIPTION) __attribute__((deprecated(DESCRIPTION))) 195 | 196 | #endif /* ZXNavigationBarDefine_h */ 197 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarDefine.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBarDefine.h 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #ifndef ZXNavigationBarDefine_h 11 | #define ZXNavigationBarDefine_h 12 | #define ZXNavDefalutBacColor [UIColor whiteColor] 13 | #define ZXNavDefalutTitleColor [UIColor blackColor] 14 | #define ZXNavDefalutLineColor [UIColor colorWithRed:220 / 255.0 green:220 / 255.0 blue:220 / 255.0 alpha:0.8] 15 | #define ZXNavDefalutItemTextColor [UIColor blackColor] 16 | 17 | #define ZXNavDefalutTitleSize 17 18 | #define ZXNavDefalutSubTitleSize 10 19 | #define ZXNavDefalutItemFontSize 15 20 | 21 | #define ZXNavDefalutItemSize 22 22 | #define ZXNavDefalutItemMargin 10 23 | 24 | #define ZXNavHistoryStackCellHeight 44 25 | #define ZXNavHistoryStackCellTitleX 16 26 | #define ZXNavHistoryStackViewWidth 250 27 | #define ZXNavHistoryStackViewItemMaxLength 6 28 | #define ZXNavHistoryStackViewStyleDarkBackgroundColor [UIColor colorWithRed:16 / 255.0 green:16 / 255.0 blue:16 / 255.0 alpha:1] 29 | #define ZXNavHistoryStackViewStyleDarkSelectedColor [UIColor colorWithRed:66 / 255.0 green:66 / 255.0 blue:66 / 255.0 alpha:1] 30 | #define ZXNavHistoryStackViewStyleLightBackgroundColor [UIColor colorWithRed:255.0 / 255.0 green:255.0 / 255.0 blue:255.0 / 255.0 alpha:1] 31 | #define ZXNavHistoryStackViewStyleLightSelectedColor [UIColor colorWithRed:225 / 255.0 green:225 / 255.0 blue:225 / 255.0 alpha:1] 32 | 33 | /** 34 | 获取主Window 35 | 36 | @return 主Window 37 | */ 38 | #define ZXMainWindow ([UIApplication sharedApplication].keyWindow ?: [UIApplication sharedApplication].windows.firstObject) 39 | 40 | /** 41 | 获取是否是iPad设备 42 | 43 | @return 是否是iPad设备 44 | */ 45 | #define ZXIsIPad ([[UIDevice currentDevice] userInterfaceIdiom]==UIUserInterfaceIdiomPad) 46 | 47 | /** 48 | 判断是否是刘海屏(全面屏iPad不算) 49 | 50 | @return 是否是刘海屏(全面屏iPad不算) 51 | */ 52 | #define ZXIsBangScreen ({\ 53 | int cFlag = 0;\ 54 | if(ZXIsIPad){cFlag = 0;}\ 55 | else if(@available(iOS 11.0, *)){\ 56 | if(ZXMainWindow.safeAreaInsets.bottom > 0){\ 57 | cFlag = 1;\ 58 | }else{\ 59 | cFlag = 0;\ 60 | }\ 61 | }else{\ 62 | cFlag = 0;\ 63 | }\ 64 | cFlag;\ 65 | }) 66 | 67 | /** 68 | 是否是全面屏iPad 69 | 70 | @return 是否是全面屏iPad 71 | */ 72 | #define ZXIsFullScreenIpad ({\ 73 | int cFlag = 0;\ 74 | if(@available(iOS 11.0, *)){\ 75 | if(ZXMainWindow.safeAreaInsets.bottom > 0 && ZXIsIPad){\ 76 | cFlag = 1;\ 77 | }else{\ 78 | cFlag = 0;\ 79 | }\ 80 | }else{\ 81 | cFlag = 0;\ 82 | }\ 83 | cFlag;\ 84 | }) 85 | 86 | /** 87 | 判断手机是否是横屏 88 | 89 | @return 手机是否是横屏 90 | */ 91 | #define ZXIsHorizontalScreen ([UIApplication sharedApplication].statusBarOrientation == UIDeviceOrientationLandscapeRight || [UIApplication sharedApplication].statusBarOrientation == UIDeviceOrientationLandscapeLeft) 92 | 93 | /** 94 | 获取屏幕宽度 95 | 96 | @return 屏幕宽度 97 | */ 98 | #define ZXScreenWidth [UIScreen mainScreen].bounds.size.width 99 | 100 | /** 101 | 获取屏幕高度 102 | 103 | @return 屏幕高度 104 | */ 105 | #define ZXScreenHeight [UIScreen mainScreen].bounds.size.height 106 | 107 | /** 108 | 获取导航栏高度(不包含状态栏高度) 109 | 110 | @return 导航栏高度(不包含状态栏高度) 111 | */ 112 | #define ZXNavBarHeightNotIncludeStatusBar (ZXIsIPad ? 50 : 44) 113 | 114 | 115 | /** 116 | 获取iPhone设备状态栏高度 117 | 118 | @return iPhone设备状态栏高度 119 | */ 120 | #define ZXIPhoneAppStatusBarHeight ({\ 121 | int height = 0;\ 122 | if(@available(iOS 13.0, *)){\ 123 | height = [[UIApplication sharedApplication] statusBarFrame].size.height != 0 ? [[UIApplication sharedApplication] statusBarFrame].size.height : (ZXIsBangScreen ? 44 : 20);\ 124 | }else{\ 125 | height = (ZXIsBangScreen ? 44 : 20);\ 126 | }\ 127 | height;\ 128 | }) 129 | 130 | /** 131 | 获取状态栏高度 132 | 133 | @return 状态栏高度 134 | */ 135 | //#define ZXAppStatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height 136 | //适配iOS13以下系统开启热点或音视频时的导航栏(因为iOS13以下系统开启或音视频时状态栏会增高,从而导致计算出来的整个导航栏增高) 137 | #define ZXAppStatusBarHeight (ZXIsHorizontalScreen ? ZXRealAppStatusBarHeight : ZXIsFullScreenIpad ? ZXRealAppStatusBarHeight : ZXIPhoneAppStatusBarHeight) 138 | 139 | 140 | /** 141 | 获取真实状态栏高度 142 | 143 | @return 真实状态栏高度 144 | */ 145 | #define ZXRealAppStatusBarHeight [[UIApplication sharedApplication] statusBarFrame].size.height 146 | 147 | /** 148 | 获取导航栏高度 149 | 150 | @return 导航栏高度 151 | */ 152 | #define ZXNavBarHeight (ZXAppStatusBarHeight + ZXNavBarHeightNotIncludeStatusBar) 153 | 154 | /** 155 | 获取安全区域顶部高度 156 | 157 | @return 安全区域顶部高度 158 | */ 159 | #define ZXSafeAreaTop ({\ 160 | int height = 0;\ 161 | if (@available(iOS 11.0, *)) {\ 162 | height = ZXMainWindow.safeAreaInsets.top;\ 163 | }else{\ 164 | height = 0;\ 165 | }\ 166 | height;\ 167 | }) 168 | 169 | /** 170 | 获取安全区域底部高度 171 | 172 | @return 安全区域底部高度 173 | */ 174 | #define ZXSafeAreaBottom ({\ 175 | int height = 0;\ 176 | if (@available(iOS 11.0, *)) {\ 177 | height = ZXMainWindow.safeAreaInsets.bottom;\ 178 | }else{\ 179 | height = 0;\ 180 | }\ 181 | height;\ 182 | }) 183 | 184 | /** 185 | 获取横屏后左右安全距离 186 | 187 | @return 横屏后左右安全距离 188 | */ 189 | #define ZXHorizontaledSafeArea ((ZXIsHorizontalScreen && ZXIsBangScreen)? ZXNavBarHeightNotIncludeStatusBar : 0) 190 | 191 | /** 192 | 属性过期标注 193 | */ 194 | #define ZXNavigationBarDeprecated(DESCRIPTION) __attribute__((deprecated(DESCRIPTION))) 195 | 196 | #endif /* ZXNavigationBarDefine_h */ 197 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/Demo/DemoCustomNavViewController/DemoCustomNav/DemoCustomNav.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackContentView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackContentView.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavHistoryStackContentView.h" 11 | #import "ZXNavHistoryStackCell.h" 12 | 13 | #import "ZXNavigationBarDefine.h" 14 | #import "UIView+ZXNavFrameExtension.h" 15 | 16 | #import 17 | static NSString *historyStackViewCellReuseIdentifier = @"ZXNavHistoryStackCell"; 18 | @interface ZXNavHistoryStackContentView() 19 | @property (strong, nonatomic) UIView *coverView; 20 | @property (assign, nonatomic) BOOL isShowed; 21 | @property (strong, nonatomic) ZXNavHistoryStackModel *selectedHistoryStackModel; 22 | @end 23 | @implementation ZXNavHistoryStackContentView 24 | 25 | #pragma mark - Init 26 | - (instancetype)initWithFrame:(CGRect)frame{ 27 | self = [super initWithFrame:frame]; 28 | if(self){ 29 | [self setUp]; 30 | } 31 | return self; 32 | } 33 | 34 | - (void)setUp{ 35 | [self addSubview:self.coverView]; 36 | [self addSubview:self.zx_historyStackView]; 37 | self.zx_historyStackView.delegate = self; 38 | self.zx_historyStackView.dataSource = self; 39 | [self.zx_historyStackView registerClass:[ZXNavHistoryStackCell class] forCellWithReuseIdentifier:historyStackViewCellReuseIdentifier]; 40 | self.coverView.userInteractionEnabled = YES; 41 | UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(coverViewTouch)]; 42 | UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(coverViewTouch)]; 43 | [self.coverView addGestureRecognizer:panGestureRecognizer]; 44 | [self.coverView addGestureRecognizer:tapGestureRecognizer]; 45 | 46 | 47 | [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(orientationDidChange:)name:UIDeviceOrientationDidChangeNotification object:nil]; 48 | } 49 | 50 | - (void)layoutSubviews{ 51 | [super layoutSubviews]; 52 | self.frame = [UIScreen mainScreen].bounds; 53 | self.coverView.frame = self.frame; 54 | if(self.isShowed){ 55 | [self updateHistoryStackViewFrameWithHide:NO]; 56 | } 57 | } 58 | 59 | - (void)coverViewTouch{ 60 | if(self.isShowed){ 61 | [self zx_hide]; 62 | } 63 | } 64 | 65 | - (instancetype)zx_show{ 66 | [ZXMainWindow addSubview:self]; 67 | [self updateHistoryStackViewFrameWithHide:YES]; 68 | [UIView animateWithDuration:0.2 animations:^{ 69 | self.coverView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.05]; 70 | [self updateHistoryStackViewFrameWithHide:NO]; 71 | }completion:^(BOOL finished) { 72 | self.isShowed = YES; 73 | }]; 74 | 75 | return self; 76 | } 77 | 78 | - (void)zx_hide{ 79 | self.isShowed = NO; 80 | [UIView animateWithDuration:0.15 animations:^{ 81 | self.coverView.backgroundColor = [UIColor colorWithWhite:0 alpha:0]; 82 | [self updateHistoryStackViewFrameWithHide:YES]; 83 | }completion:^(BOOL finished) { 84 | [self removeFromSuperview]; 85 | }]; 86 | } 87 | 88 | - (void)updateHistoryStackViewFrameWithHide:(BOOL)isHide{ 89 | if(isHide){ 90 | self.zx_historyStackView.frame = CGRectMake(self.zx_historyStackViewLeft + 20, ZXAppStatusBarHeight + ZXNavHistoryStackCellHeight / 2, 0, 0); 91 | }else{ 92 | self.zx_historyStackView.frame = CGRectMake(self.zx_historyStackViewLeft, ZXAppStatusBarHeight, ZXNavHistoryStackViewWidth, self.zx_historyStackArray.count * ZXNavHistoryStackCellHeight); 93 | } 94 | } 95 | 96 | #pragma mark - UICollectionViewDelegate 97 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ 98 | return CGSizeMake(self.zx_historyStackView.frame.size.width, ZXNavHistoryStackCellHeight); 99 | } 100 | 101 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ 102 | ZXNavHistoryStackModel *historyStackModel = self.zx_historyStackArray[indexPath.row]; 103 | [self doPopViewController:historyStackModel]; 104 | } 105 | 106 | #pragma mark - UICollectionViewDataSource 107 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ 108 | return self.zx_historyStackArray.count; 109 | } 110 | 111 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ 112 | ZXNavHistoryStackCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:historyStackViewCellReuseIdentifier forIndexPath:indexPath]; 113 | cell.historyStackViewStyle = self.zx_historyStackViewStyle; 114 | cell.historyStackModel = self.zx_historyStackArray[indexPath.row]; 115 | return cell; 116 | } 117 | 118 | #pragma mark - Private 119 | - (void)handlePanGestureWithPoint:(CGPoint)point{ 120 | if(point.x > CGRectGetMaxX(self.zx_historyStackView.frame) || point.y > CGRectGetMaxY(self.zx_historyStackView.frame)){ 121 | if(self.selectedHistoryStackModel){ 122 | self.selectedHistoryStackModel.isSelected = NO; 123 | self.selectedHistoryStackModel = nil; 124 | [self.zx_historyStackView reloadData]; 125 | } 126 | }else{ 127 | if(self.selectedHistoryStackModel){ 128 | self.selectedHistoryStackModel.isSelected = NO; 129 | } 130 | NSIndexPath *indexPath = [self.zx_historyStackView indexPathForItemAtPoint:point]; 131 | ZXNavHistoryStackModel *historyStackModel = self.zx_historyStackArray[indexPath.row]; 132 | if(indexPath && !(self.selectedHistoryStackModel && self.selectedHistoryStackModel == historyStackModel)){ 133 | historyStackModel.isSelected = YES; 134 | [self.zx_historyStackView reloadData]; 135 | self.selectedHistoryStackModel = historyStackModel; 136 | if (@available(iOS 10.0, *)){ 137 | UIImpactFeedbackGenerator *impactFeedbackGenerator = [[UIImpactFeedbackGenerator alloc]initWithStyle:UIImpactFeedbackStyleLight]; 138 | [impactFeedbackGenerator impactOccurred]; 139 | } 140 | } 141 | } 142 | } 143 | 144 | - (void)handlePanGestureEnd{ 145 | [self doPopViewController:self.selectedHistoryStackModel]; 146 | } 147 | 148 | 149 | - (void)doPopViewController:(ZXNavHistoryStackModel *)historyStackModel{ 150 | if(historyStackModel && historyStackModel.viewController && historyStackModel.viewController.navigationController){ 151 | [historyStackModel.viewController.navigationController popToViewController:historyStackModel.viewController animated:YES]; 152 | [self zx_hide]; 153 | } 154 | } 155 | 156 | - (void)orientationDidChange:(NSNotification *)sender{ 157 | if(self.isShowed){ 158 | [self zx_hide]; 159 | } 160 | } 161 | 162 | #pragma mark - LazyLoad 163 | - (ZXNavHistoryStackView *)zx_historyStackView{ 164 | if(!_zx_historyStackView){ 165 | UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; 166 | flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; 167 | flowLayout.minimumInteritemSpacing = 0; 168 | flowLayout.minimumLineSpacing = 0; 169 | _zx_historyStackView = [[ZXNavHistoryStackView alloc]initWithFrame:CGRectZero collectionViewLayout:flowLayout]; 170 | _zx_historyStackView.backgroundColor = [UIColor whiteColor]; 171 | _zx_historyStackView.clipsToBounds = YES; 172 | _zx_historyStackView.layer.cornerRadius = 12; 173 | if(self.zx_historyStackViewStyle == ZXNavHistoryStackViewStyleLight){ 174 | _zx_historyStackView.backgroundColor = ZXNavHistoryStackViewStyleLightBackgroundColor; 175 | }else{ 176 | _zx_historyStackView.backgroundColor = ZXNavHistoryStackViewStyleDarkBackgroundColor; 177 | } 178 | 179 | } 180 | return _zx_historyStackView; 181 | } 182 | 183 | - (UIView *)coverView{ 184 | if(!_coverView){ 185 | _coverView = [[UIView alloc]init]; 186 | } 187 | return _coverView; 188 | } 189 | 190 | - (void)setZx_historyStackArray:(NSMutableArray *)zx_historyStackArray{ 191 | _zx_historyStackArray = zx_historyStackArray; 192 | if(zx_historyStackArray.count){ 193 | ZXNavHistoryStackModel *firstHistoryStackModel = zx_historyStackArray.firstObject; 194 | ZXNavHistoryStackModel *lastHistoryStackModel = zx_historyStackArray.lastObject; 195 | firstHistoryStackModel.isSelected = YES; 196 | self.selectedHistoryStackModel = firstHistoryStackModel; 197 | lastHistoryStackModel.isLast = YES; 198 | } 199 | } 200 | 201 | - (void)setZx_historyStackViewStyle:(ZXNavHistoryStackViewStyle)zx_historyStackViewStyle{ 202 | _zx_historyStackViewStyle = zx_historyStackViewStyle; 203 | [self.zx_historyStackView reloadData]; 204 | } 205 | 206 | - (void)setZx_historyStackViewLeft:(CGFloat)zx_historyStackViewLeft{ 207 | _zx_historyStackViewLeft = zx_historyStackViewLeft; 208 | self.zx_historyStackView.zx_x = zx_historyStackViewLeft; 209 | } 210 | 211 | - (void)dealloc{ 212 | [[NSNotificationCenter defaultCenter]removeObserver:self]; 213 | } 214 | 215 | @end 216 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarSubViews/ZXNavHistoryStackView/View/ZXNavHistoryStackContentView.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavHistoryStackContentView.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/12/22. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavHistoryStackContentView.h" 11 | #import "ZXNavHistoryStackCell.h" 12 | 13 | #import "ZXNavigationBarDefine.h" 14 | #import "UIView+ZXNavFrameExtension.h" 15 | 16 | #import 17 | static NSString *historyStackViewCellReuseIdentifier = @"ZXNavHistoryStackCell"; 18 | @interface ZXNavHistoryStackContentView() 19 | @property (strong, nonatomic) UIView *coverView; 20 | @property (assign, nonatomic) BOOL isShowed; 21 | @property (strong, nonatomic) ZXNavHistoryStackModel *selectedHistoryStackModel; 22 | @end 23 | @implementation ZXNavHistoryStackContentView 24 | 25 | #pragma mark - Init 26 | - (instancetype)initWithFrame:(CGRect)frame{ 27 | self = [super initWithFrame:frame]; 28 | if(self){ 29 | [self setUp]; 30 | } 31 | return self; 32 | } 33 | 34 | - (void)setUp{ 35 | [self addSubview:self.coverView]; 36 | [self addSubview:self.zx_historyStackView]; 37 | self.zx_historyStackView.delegate = self; 38 | self.zx_historyStackView.dataSource = self; 39 | [self.zx_historyStackView registerClass:[ZXNavHistoryStackCell class] forCellWithReuseIdentifier:historyStackViewCellReuseIdentifier]; 40 | self.coverView.userInteractionEnabled = YES; 41 | UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(coverViewTouch)]; 42 | UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(coverViewTouch)]; 43 | [self.coverView addGestureRecognizer:panGestureRecognizer]; 44 | [self.coverView addGestureRecognizer:tapGestureRecognizer]; 45 | 46 | 47 | [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(orientationDidChange:)name:UIDeviceOrientationDidChangeNotification object:nil]; 48 | } 49 | 50 | - (void)layoutSubviews{ 51 | [super layoutSubviews]; 52 | self.frame = [UIScreen mainScreen].bounds; 53 | self.coverView.frame = self.frame; 54 | if(self.isShowed){ 55 | [self updateHistoryStackViewFrameWithHide:NO]; 56 | } 57 | } 58 | 59 | - (void)coverViewTouch{ 60 | if(self.isShowed){ 61 | [self zx_hide]; 62 | } 63 | } 64 | 65 | - (instancetype)zx_show{ 66 | [ZXMainWindow addSubview:self]; 67 | [self updateHistoryStackViewFrameWithHide:YES]; 68 | [UIView animateWithDuration:0.2 animations:^{ 69 | self.coverView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.05]; 70 | [self updateHistoryStackViewFrameWithHide:NO]; 71 | }completion:^(BOOL finished) { 72 | self.isShowed = YES; 73 | }]; 74 | 75 | return self; 76 | } 77 | 78 | - (void)zx_hide{ 79 | self.isShowed = NO; 80 | [UIView animateWithDuration:0.15 animations:^{ 81 | self.coverView.backgroundColor = [UIColor colorWithWhite:0 alpha:0]; 82 | [self updateHistoryStackViewFrameWithHide:YES]; 83 | }completion:^(BOOL finished) { 84 | [self removeFromSuperview]; 85 | }]; 86 | } 87 | 88 | - (void)updateHistoryStackViewFrameWithHide:(BOOL)isHide{ 89 | if(isHide){ 90 | self.zx_historyStackView.frame = CGRectMake(self.zx_historyStackViewLeft + 20, ZXAppStatusBarHeight + ZXNavHistoryStackCellHeight / 2, 0, 0); 91 | }else{ 92 | self.zx_historyStackView.frame = CGRectMake(self.zx_historyStackViewLeft, ZXAppStatusBarHeight, ZXNavHistoryStackViewWidth, self.zx_historyStackArray.count * ZXNavHistoryStackCellHeight); 93 | } 94 | } 95 | 96 | #pragma mark - UICollectionViewDelegate 97 | - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ 98 | return CGSizeMake(self.zx_historyStackView.frame.size.width, ZXNavHistoryStackCellHeight); 99 | } 100 | 101 | - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{ 102 | ZXNavHistoryStackModel *historyStackModel = self.zx_historyStackArray[indexPath.row]; 103 | [self doPopViewController:historyStackModel]; 104 | } 105 | 106 | #pragma mark - UICollectionViewDataSource 107 | - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{ 108 | return self.zx_historyStackArray.count; 109 | } 110 | 111 | - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ 112 | ZXNavHistoryStackCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:historyStackViewCellReuseIdentifier forIndexPath:indexPath]; 113 | cell.historyStackViewStyle = self.zx_historyStackViewStyle; 114 | cell.historyStackModel = self.zx_historyStackArray[indexPath.row]; 115 | return cell; 116 | } 117 | 118 | #pragma mark - Private 119 | - (void)handlePanGestureWithPoint:(CGPoint)point{ 120 | if(point.x > CGRectGetMaxX(self.zx_historyStackView.frame) || point.y > CGRectGetMaxY(self.zx_historyStackView.frame)){ 121 | if(self.selectedHistoryStackModel){ 122 | self.selectedHistoryStackModel.isSelected = NO; 123 | self.selectedHistoryStackModel = nil; 124 | [self.zx_historyStackView reloadData]; 125 | } 126 | }else{ 127 | if(self.selectedHistoryStackModel){ 128 | self.selectedHistoryStackModel.isSelected = NO; 129 | } 130 | NSIndexPath *indexPath = [self.zx_historyStackView indexPathForItemAtPoint:point]; 131 | ZXNavHistoryStackModel *historyStackModel = self.zx_historyStackArray[indexPath.row]; 132 | if(indexPath && !(self.selectedHistoryStackModel && self.selectedHistoryStackModel == historyStackModel)){ 133 | historyStackModel.isSelected = YES; 134 | [self.zx_historyStackView reloadData]; 135 | self.selectedHistoryStackModel = historyStackModel; 136 | if (@available(iOS 10.0, *)){ 137 | UIImpactFeedbackGenerator *impactFeedbackGenerator = [[UIImpactFeedbackGenerator alloc]initWithStyle:UIImpactFeedbackStyleLight]; 138 | [impactFeedbackGenerator impactOccurred]; 139 | } 140 | } 141 | } 142 | } 143 | 144 | - (void)handlePanGestureEnd{ 145 | [self doPopViewController:self.selectedHistoryStackModel]; 146 | } 147 | 148 | 149 | - (void)doPopViewController:(ZXNavHistoryStackModel *)historyStackModel{ 150 | if(historyStackModel && historyStackModel.viewController && historyStackModel.viewController.navigationController){ 151 | [historyStackModel.viewController.navigationController popToViewController:historyStackModel.viewController animated:YES]; 152 | [self zx_hide]; 153 | } 154 | } 155 | 156 | - (void)orientationDidChange:(NSNotification *)sender{ 157 | if(self.isShowed){ 158 | [self zx_hide]; 159 | } 160 | } 161 | 162 | #pragma mark - LazyLoad 163 | - (ZXNavHistoryStackView *)zx_historyStackView{ 164 | if(!_zx_historyStackView){ 165 | UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; 166 | flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; 167 | flowLayout.minimumInteritemSpacing = 0; 168 | flowLayout.minimumLineSpacing = 0; 169 | _zx_historyStackView = [[ZXNavHistoryStackView alloc]initWithFrame:CGRectZero collectionViewLayout:flowLayout]; 170 | _zx_historyStackView.backgroundColor = [UIColor whiteColor]; 171 | _zx_historyStackView.clipsToBounds = YES; 172 | _zx_historyStackView.layer.cornerRadius = 12; 173 | if(self.zx_historyStackViewStyle == ZXNavHistoryStackViewStyleLight){ 174 | _zx_historyStackView.backgroundColor = ZXNavHistoryStackViewStyleLightBackgroundColor; 175 | }else{ 176 | _zx_historyStackView.backgroundColor = ZXNavHistoryStackViewStyleDarkBackgroundColor; 177 | } 178 | 179 | } 180 | return _zx_historyStackView; 181 | } 182 | 183 | - (UIView *)coverView{ 184 | if(!_coverView){ 185 | _coverView = [[UIView alloc]init]; 186 | } 187 | return _coverView; 188 | } 189 | 190 | - (void)setZx_historyStackArray:(NSMutableArray *)zx_historyStackArray{ 191 | _zx_historyStackArray = zx_historyStackArray; 192 | if(zx_historyStackArray.count){ 193 | ZXNavHistoryStackModel *firstHistoryStackModel = zx_historyStackArray.firstObject; 194 | ZXNavHistoryStackModel *lastHistoryStackModel = zx_historyStackArray.lastObject; 195 | firstHistoryStackModel.isSelected = YES; 196 | self.selectedHistoryStackModel = firstHistoryStackModel; 197 | lastHistoryStackModel.isLast = YES; 198 | } 199 | } 200 | 201 | - (void)setZx_historyStackViewStyle:(ZXNavHistoryStackViewStyle)zx_historyStackViewStyle{ 202 | _zx_historyStackViewStyle = zx_historyStackViewStyle; 203 | [self.zx_historyStackView reloadData]; 204 | } 205 | 206 | - (void)setZx_historyStackViewLeft:(CGFloat)zx_historyStackViewLeft{ 207 | _zx_historyStackViewLeft = zx_historyStackViewLeft; 208 | self.zx_historyStackView.zx_x = zx_historyStackViewLeft; 209 | } 210 | 211 | - (void)dealloc{ 212 | [[NSNotificationCenter defaultCenter]removeObserver:self]; 213 | } 214 | 215 | @end 216 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarSubViews/ZXNavItemBtn.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavItemBtn.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/3/7. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavItemBtn.h" 11 | #import "ZXNavigationBarDefine.h" 12 | #import "UIImage+ZXNavColorRender.h" 13 | #import "NSString+ZXNavCalcSizeExtension.h" 14 | #import "NSAttributedString+ZXNavCalcSizeExtension.h" 15 | @interface ZXNavItemBtn() 16 | ///NavItemBtn frame发生改变时的回调 17 | @property(copy, nonatomic)void(^zx_frameUpdateBlock)(CGRect frame); 18 | @end 19 | @implementation ZXNavItemBtn 20 | #pragma mark - Init 21 | - (instancetype)initWithCoder:(NSCoder *)coder{ 22 | self = [super initWithCoder:coder]; 23 | if(self){ 24 | [self setUp]; 25 | } 26 | return self; 27 | } 28 | 29 | - (void)awakeFromNib{ 30 | [super awakeFromNib]; 31 | [self setUp]; 32 | } 33 | 34 | - (instancetype)initWithFrame:(CGRect)frame{ 35 | self = [super initWithFrame:frame]; 36 | if(self){ 37 | [self setUp]; 38 | } 39 | return self; 40 | } 41 | 42 | - (void)setUp{ 43 | self.zx_fixWidth = -1; 44 | self.zx_fixHeight = -1; 45 | self.zx_fixMarginLeft = -1; 46 | self.zx_fixMarginRight = -1; 47 | self.zx_fixImageSize = CGSizeZero; 48 | } 49 | 50 | #pragma mark - Public 51 | - (void)zx_updateLayout{ 52 | [self zx_layoutImageAndTitle]; 53 | [self noticeUpdateFrame]; 54 | } 55 | 56 | #pragma mark - Setter 57 | - (void)setTitle:(NSString *)title forState:(UIControlState)state{ 58 | if(self.zx_customView && title && title.length){ 59 | return; 60 | } 61 | [super setTitle:title forState:state]; 62 | if(self.zx_tintColor){ 63 | [self setTitleColor:self.zx_tintColor forState:state]; 64 | } 65 | [self zx_layoutImageAndTitle]; 66 | [self noticeUpdateFrame]; 67 | } 68 | 69 | - (void)setAttributedTitle:(NSAttributedString *)title forState:(UIControlState)state{ 70 | if(self.zx_customView && title && title.length){ 71 | return; 72 | } 73 | [super setAttributedTitle:title forState:state]; 74 | [self zx_layoutImageAndTitle]; 75 | [self noticeUpdateFrame]; 76 | } 77 | 78 | - (void)setImage:(UIImage *)image forState:(UIControlState)state{ 79 | if(self.zx_customView && image){ 80 | return; 81 | } 82 | if(self.zx_tintColor){ 83 | image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; 84 | }else{ 85 | image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; 86 | } 87 | [super setImage:image forState:state]; 88 | if(!image){ 89 | self.imageView.image = image; 90 | } 91 | [self zx_layoutImageAndTitle]; 92 | [self noticeUpdateFrame]; 93 | } 94 | 95 | - (void)setZx_tintColor:(UIColor *)zx_tintColor{ 96 | _zx_tintColor = zx_tintColor; 97 | self.tintColor = zx_tintColor; 98 | [self resetImage]; 99 | [self resetTitle]; 100 | } 101 | 102 | 103 | - (void)setZx_imageColor:(UIColor *)zx_imageColor{ 104 | _zx_imageColor = zx_imageColor; 105 | self.tintColor = zx_imageColor; 106 | [self resetImage]; 107 | } 108 | 109 | - (void)setZx_disableAutoLayoutImageAndTitle:(BOOL )zx_disableAutoLayoutImageAndTitle{ 110 | _zx_disableAutoLayoutImageAndTitle = zx_disableAutoLayoutImageAndTitle; 111 | [self zx_layoutImageAndTitle]; 112 | [self noticeUpdateFrame]; 113 | } 114 | 115 | - (void)setZx_fixWidth:(CGFloat)zx_fixWidth{ 116 | _zx_fixWidth = zx_fixWidth; 117 | [self.superview setValue:@1 forKey:@"shouldRefLayout"]; 118 | [self noticeUpdateFrame]; 119 | } 120 | 121 | - (void)setZx_fixHeight:(CGFloat)zx_fixHeight{ 122 | _zx_fixHeight = zx_fixHeight; 123 | [self.superview setValue:@1 forKey:@"shouldRefLayout"]; 124 | [self noticeUpdateFrame]; 125 | } 126 | 127 | - (void)setZx_fixMarginLeft:(CGFloat)zx_fixMarginLeft{ 128 | _zx_fixMarginLeft = zx_fixMarginLeft; 129 | [self.superview setValue:@1 forKey:@"shouldRefLayout"]; 130 | [self noticeUpdateFrame]; 131 | } 132 | 133 | - (void)setZx_fixMarginRight:(CGFloat)zx_fixMarginRight{ 134 | _zx_fixMarginRight = zx_fixMarginRight; 135 | [self.superview setValue:@1 forKey:@"shouldRefLayout"]; 136 | [self noticeUpdateFrame]; 137 | } 138 | 139 | - (void)setZx_fontSize:(CGFloat)zx_fontSize{ 140 | _zx_fontSize = zx_fontSize; 141 | self.titleLabel.font = [UIFont systemFontOfSize:zx_fontSize]; 142 | [self.superview setValue:@1 forKey:@"shouldRefLayout"]; 143 | [self zx_layoutImageAndTitle]; 144 | [self noticeUpdateFrame]; 145 | } 146 | 147 | - (void)setZx_fixImageSize:(CGSize)zx_fixImageSize{ 148 | _zx_fixImageSize = zx_fixImageSize; 149 | [self.superview setValue:@1 forKey:@"shouldRefLayout"]; 150 | [self zx_layoutImageAndTitle]; 151 | [self noticeUpdateFrame]; 152 | } 153 | 154 | - (void)setZx_textAttachWidth:(CGFloat)zx_textAttachWidth{ 155 | _zx_textAttachWidth = zx_textAttachWidth; 156 | [self.superview setValue:@1 forKey:@"shouldRefLayout"]; 157 | [self zx_layoutImageAndTitle]; 158 | [self noticeUpdateFrame]; 159 | } 160 | 161 | - (void)setZx_textAttachHeight:(CGFloat)zx_textAttachHeight{ 162 | _zx_textAttachHeight = zx_textAttachHeight; 163 | [self.superview setValue:@1 forKey:@"shouldRefLayout"]; 164 | [self zx_layoutImageAndTitle]; 165 | [self noticeUpdateFrame]; 166 | } 167 | 168 | - (void)setZx_setCornerRadiusRounded:(BOOL)zx_setCornerRadiusRounded{ 169 | _zx_setCornerRadiusRounded = zx_setCornerRadiusRounded; 170 | [self noticeUpdateFrame]; 171 | } 172 | 173 | - (void)setZx_imageOffsetX:(CGFloat)zx_imageOffsetX{ 174 | _zx_imageOffsetX = zx_imageOffsetX; 175 | [self zx_layoutImageAndTitle]; 176 | } 177 | 178 | - (void)setZx_customView:(UIView *)zx_customView{ 179 | if(!zx_customView){ 180 | if([self.subviews containsObject:_zx_customView]){ 181 | [_zx_customView removeFromSuperview]; 182 | } 183 | _zx_customView = nil; 184 | [self noticeUpdateFrame]; 185 | return; 186 | } 187 | _zx_customView = zx_customView; 188 | if(![self.subviews containsObject:zx_customView]){ 189 | [self addSubview:zx_customView]; 190 | } 191 | if(CGRectEqualToRect(zx_customView.frame, CGRectZero)){ 192 | CGFloat customViewWidth = self.zx_fixWidth < 0 ? ZXNavDefalutItemSize : self.zx_fixWidth; 193 | CGFloat customViewHeight = self.zx_fixHeight < 0 ? ZXNavDefalutItemSize : self.zx_fixWidth; 194 | zx_customView.frame = CGRectMake(0, 0, customViewWidth, customViewHeight); 195 | } 196 | if(zx_customView.frame.size.width){ 197 | self.zx_fixWidth = zx_customView.frame.size.width + zx_customView.frame.origin.x * 2; 198 | } 199 | if(zx_customView.frame.size.height){ 200 | self.zx_fixHeight = zx_customView.frame.size.height + zx_customView.frame.origin.y * 2; 201 | } 202 | [self setImage:nil forState:UIControlStateNormal]; 203 | [self setTitle:@"" forState:UIControlStateNormal]; 204 | [self setAttributedTitle:nil forState:UIControlStateNormal]; 205 | } 206 | 207 | #pragma mark - pirvate 208 | - (void)noticeUpdateFrame{ 209 | if(self.zx_barItemBtnFrameUpdateBlock){ 210 | self.zx_barItemBtnFrameUpdateBlock(self); 211 | } 212 | } 213 | 214 | - (void)layoutSubviews{ 215 | [super layoutSubviews]; 216 | [self zx_layoutImageAndTitle]; 217 | } 218 | 219 | - (void)resetImage{ 220 | BOOL isStateFocused = NO; 221 | if(@available(iOS 9.0, *)){ 222 | isStateFocused = self.state == UIControlStateFocused; 223 | } 224 | if(self.zx_useTintColorOnlyInStateNormal || isStateFocused){ 225 | [self setImage:[self imageForState:UIControlStateNormal] forState:UIControlStateNormal]; 226 | }else{ 227 | [self setImage:self.currentImage forState:self.state]; 228 | } 229 | } 230 | 231 | 232 | - (void)resetTitle{ 233 | BOOL isStateFocused = NO; 234 | if(@available(iOS 9.0, *)){ 235 | isStateFocused = self.state == UIControlStateFocused; 236 | } 237 | if(self.zx_useTintColorOnlyInStateNormal || isStateFocused){ 238 | [self setTitle:[self titleForState:UIControlStateNormal] forState:UIControlStateNormal]; 239 | }else{ 240 | [self setTitle:self.currentTitle forState:self.state]; 241 | } 242 | } 243 | 244 | #pragma mark ButtonLayout 245 | - (void)zx_layoutImageAndTitle{ 246 | if(self.zx_disableAutoLayoutImageAndTitle){ 247 | return; 248 | } 249 | CGFloat btnw = 0; 250 | if(self.currentAttributedTitle){ 251 | btnw = [self.currentAttributedTitle zx_getAttrRectWidthWithLimitH:self.frame.size.height fontSize:self.titleLabel.font.pointSize] + 5; 252 | }else{ 253 | if(self.currentTitle && self.currentTitle.length){ 254 | btnw = [self.currentTitle zx_getRectWidthWithLimitH:self.frame.size.height fontSize:self.titleLabel.font.pointSize] + 5; 255 | } 256 | 257 | } 258 | btnw += self.zx_textAttachWidth; 259 | if(self.imageView.image){ 260 | BOOL useFixImageSize = NO; 261 | CGFloat imageHeight = self.frame.size.height; 262 | CGFloat imageWidth = self.frame.size.height; 263 | if(!CGSizeEqualToSize(self.zx_fixImageSize,CGSizeZero)){ 264 | imageHeight = self.zx_fixImageSize.height; 265 | imageWidth = self.zx_fixImageSize.width; 266 | useFixImageSize = YES; 267 | } 268 | CGFloat imageViewX = 0; 269 | if(!(self.currentTitle.length || self.currentAttributedTitle.length) && useFixImageSize){ 270 | imageViewX = (self.frame.size.width - imageWidth) / 2 + self.zx_imageOffsetX; 271 | } 272 | self.imageView.frame = CGRectMake(imageViewX, (self.frame.size.height - imageHeight) / 2, imageWidth, imageHeight); 273 | self.titleLabel.frame = CGRectMake(CGRectGetMaxX(self.imageView.frame), 0, btnw, self.frame.size.height); 274 | }else{ 275 | self.imageView.frame = CGRectZero; 276 | self.titleLabel.frame = CGRectMake(0, 0, btnw, self.frame.size.height); 277 | } 278 | } 279 | 280 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 281 | [super touchesBegan:touches withEvent:event]; 282 | if(self.zx_touchesBeganBlock){ 283 | self.zx_touchesBeganBlock(); 284 | } 285 | } 286 | 287 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ 288 | [super touchesEnded:touches withEvent:event]; 289 | if(self.zx_touchesEndBlock){ 290 | self.zx_touchesEndBlock(); 291 | } 292 | } 293 | 294 | @end 295 | -------------------------------------------------------------------------------- /ZXNavigationBar/ZXNavigationBarNavigationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBarNavigationController.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/5/29. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavigationBarNavigationController.h" 11 | #import 12 | #import "ZXNavigationBarController.h" 13 | #import "ZXNavigationBarTableViewController.h" 14 | @interface ZXNavigationBarNavigationController () 15 | @property (assign, nonatomic) CGFloat touchBeginX; 16 | @property (assign, nonatomic) BOOL doingPopGesture; 17 | @property (strong, nonatomic, nullable) UIViewController *zx_topViewController; 18 | @property (strong, nonatomic) id orgInteractivePopGestureRecognizerDelegate; 19 | @end 20 | 21 | @implementation ZXNavigationBarNavigationController 22 | 23 | - (void)viewDidLoad { 24 | self.orgInteractivePopGestureRecognizerDelegate = self.interactivePopGestureRecognizer.delegate; 25 | [super viewDidLoad]; 26 | self.delegate = self; 27 | self.zx_popGestureCoverRatio = 1; 28 | [self addFullScreenGesture]; 29 | } 30 | 31 | #pragma mark - 重写父类pop和push相关方法 32 | - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{ 33 | if([viewController isKindOfClass:[ZXNavigationBarController class]]){ 34 | self.navigationBarHidden = YES; 35 | } 36 | [self updateTopViewController:viewController]; 37 | if(!self.zx_disableAutoHidesBottomBarWhenPushed){ 38 | [viewController setHidesBottomBarWhenPushed:self.viewControllers.count >= 1]; 39 | } 40 | [super pushViewController:viewController animated:animated]; 41 | } 42 | 43 | - (UIViewController *)popViewControllerAnimated:(BOOL)animated{ 44 | if(self.childViewControllers.count > 1 && !self.doingPopGesture){ 45 | [self updateTopViewController:self.childViewControllers[self.childViewControllers.count - 2]]; 46 | } 47 | return [super popViewControllerAnimated:animated]; 48 | } 49 | 50 | - (NSArray *)popToRootViewControllerAnimated:(BOOL)animated{ 51 | if(self.viewControllers.firstObject && !self.doingPopGesture){ 52 | [self updateTopViewController:self.viewControllers.firstObject]; 53 | } 54 | if(!self.zx_disableAutoHidesBottomBarWhenPushed && self.viewControllers.count > 1){ 55 | self.topViewController.hidesBottomBarWhenPushed = NO; 56 | } 57 | return [super popToRootViewControllerAnimated:animated]; 58 | } 59 | 60 | - (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated{ 61 | if(viewController && !self.doingPopGesture){ 62 | [self updateTopViewController:viewController]; 63 | } 64 | return [super popToViewController:viewController animated:animated]; 65 | } 66 | 67 | #pragma mark - public 68 | - (void)zx_disablePopGesture{ 69 | if(self.zx_popGestureRecognizer){ 70 | [self.view removeGestureRecognizer:self.zx_popGestureRecognizer]; 71 | } 72 | } 73 | 74 | #pragma mark - Private 75 | #pragma mark 添加全屏手势 76 | - (void)addFullScreenGesture{ 77 | self.interactivePopGestureRecognizer.enabled = NO; 78 | UIPanGestureRecognizer *popGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handleNavigationTransition:)]; 79 | popGestureRecognizer.delegate = self; 80 | [self.view addGestureRecognizer:popGestureRecognizer]; 81 | _zx_popGestureRecognizer = popGestureRecognizer; 82 | } 83 | 84 | #pragma mark 处理pop手势 85 | - (void)handleNavigationTransition:(UIPanGestureRecognizer *)panGesture{ 86 | if(self.zx_topViewController && !self.doingPopGesture){ 87 | if([self.zx_topViewController isKindOfClass:[ZXNavigationBarTableViewController class]]){ 88 | ZXNavigationBarTableViewController *topViewController = (ZXNavigationBarTableViewController *)self.zx_topViewController; 89 | if(topViewController.zx_handlePopBlock){ 90 | BOOL shouldPop = topViewController.zx_handlePopBlock((ZXNavigationBarTableViewController *)self.zx_topViewController,ZXNavPopBlockFromPopGesture); 91 | if(!shouldPop){ 92 | return; 93 | } 94 | } 95 | }else{ 96 | ZXNavigationBarController *topViewController = (ZXNavigationBarController *)self.zx_topViewController; 97 | if(topViewController.zx_handlePopBlock){ 98 | BOOL shouldPop = topViewController.zx_handlePopBlock((ZXNavigationBarController *)self.zx_topViewController,ZXNavPopBlockFromPopGesture); 99 | if(!shouldPop){ 100 | return; 101 | } 102 | } 103 | } 104 | 105 | } 106 | if(self.zx_navHandlePopGestureBlock){ 107 | BOOL shouldPop = self.zx_navHandlePopGestureBlock(self.zx_topViewController); 108 | if(!shouldPop){ 109 | return; 110 | } 111 | } 112 | CGFloat panGestureX = [panGesture locationInView:self.view].x; 113 | self.doingPopGesture = YES; 114 | [self.orgInteractivePopGestureRecognizerDelegate performSelector:@selector(handleNavigationTransition:) withObject:panGesture]; 115 | CGFloat popOffsetX = panGestureX - self.touchBeginX; 116 | if(self.zx_handleCustomPopGesture){ 117 | if(panGesture.state == UIGestureRecognizerStateEnded){ 118 | self.doingPopGesture = NO; 119 | if(popOffsetX > self.view.frame.size.width / 2){ 120 | if(@available(iOS 10.0, *)){ 121 | 122 | }else{ 123 | self.zx_handleCustomPopGesture(self.zx_topViewController,1); 124 | } 125 | }else{ 126 | if(@available(iOS 10.0, *)){ 127 | 128 | }else{ 129 | self.zx_handleCustomPopGesture(self.zx_topViewController,0); 130 | } 131 | 132 | } 133 | }else{ 134 | if(popOffsetX >= 0){ 135 | self.zx_handleCustomPopGesture(self.zx_topViewController,(popOffsetX / self.view.frame.size.width)); 136 | }else{ 137 | self.zx_handleCustomPopGesture(self.zx_topViewController,0); 138 | } 139 | } 140 | } 141 | } 142 | 143 | #pragma mark 更新栈顶控制器 144 | - (void)updateTopViewController:(UIViewController *)viewController{ 145 | self.zx_topViewController = nil; 146 | if(viewController && ([viewController isKindOfClass:[ZXNavigationBarController class]] || [viewController isKindOfClass:[ZXNavigationBarTableViewController class]] )){ 147 | if([viewController isKindOfClass:[ZXNavigationBarController class]]){ 148 | self.zx_topViewController = (ZXNavigationBarController *)viewController; 149 | }else{ 150 | self.zx_topViewController = (ZXNavigationBarTableViewController *)viewController; 151 | } 152 | } 153 | } 154 | 155 | #pragma mark - UIGestureRecognizerDelegate 156 | - (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer{ 157 | if(gestureRecognizer != self.zx_popGestureRecognizer){ 158 | return YES; 159 | } 160 | if ([[self valueForKey:@"_isTransitioning"] boolValue]) { 161 | return NO; 162 | } 163 | /* **********************************************/ 164 | // Thanks to @forkingdog https://github.com/forkingdog/FDFullscreenPopGesture Respect! 165 | CGPoint translation = [gestureRecognizer translationInView:self.view]; 166 | BOOL isLeftToRight = [UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionLeftToRight; 167 | CGFloat multiplier = isLeftToRight ? 1 : - 1; 168 | if ((translation.x * multiplier) <= 0) { 169 | return NO; 170 | } 171 | /* **********************************************/ 172 | CGFloat panGestureX = [gestureRecognizer locationInView:self.view].x; 173 | CGFloat coverW = self.zx_popGestureCoverRatio * self.view.frame.size.width; 174 | if(panGestureX > coverW){ 175 | return NO; 176 | } 177 | self.touchBeginX = [gestureRecognizer locationInView:self.view].x; 178 | return self.childViewControllers.count != 1; 179 | } 180 | 181 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 182 | BOOL shouldRecognizeSimultaneously = NO; 183 | if(self.zx_popGestureShouldRecognizeSimultaneously){ 184 | shouldRecognizeSimultaneously = self.zx_popGestureShouldRecognizeSimultaneously(otherGestureRecognizer); 185 | } 186 | return shouldRecognizeSimultaneously; 187 | } 188 | 189 | #pragma mark - UINavigationControllerDelegate 190 | - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{ 191 | UIViewController *topViewController = self.topViewController; 192 | if(topViewController){ 193 | id transitionCoordinator = topViewController.transitionCoordinator; 194 | if(transitionCoordinator){ 195 | if(@available(iOS 10.0, *)){ 196 | [transitionCoordinator notifyWhenInteractionChangesUsingBlock:^(id context){ 197 | if([context isCancelled]){ 198 | if(self.zx_handleCustomPopGesture){ 199 | self.zx_handleCustomPopGesture(self.zx_topViewController,0); 200 | } 201 | 202 | }else{ 203 | if(self.zx_handleCustomPopGesture){ 204 | self.zx_handleCustomPopGesture(self.zx_topViewController,1); 205 | } 206 | } 207 | }]; 208 | } 209 | } 210 | } 211 | } 212 | 213 | 214 | #pragma mark - getter&setter 215 | - (void)setZx_disableFullScreenGesture:(BOOL)zx_disableFullScreenGesture{ 216 | _zx_disableFullScreenGesture = zx_disableFullScreenGesture; 217 | if(zx_disableFullScreenGesture){ 218 | self.zx_popGestureCoverRatio = 0.1; 219 | }else{ 220 | self.zx_popGestureCoverRatio = 1; 221 | } 222 | } 223 | 224 | 225 | - (void)setZx_popGestureCoverRatio:(CGFloat)zx_popGestureCoverRatio{ 226 | if(zx_popGestureCoverRatio > 1){ 227 | _zx_popGestureCoverRatio = 1; 228 | }else if(zx_popGestureCoverRatio < 0){ 229 | _zx_popGestureCoverRatio = 0; 230 | }else{ 231 | _zx_popGestureCoverRatio = zx_popGestureCoverRatio; 232 | } 233 | } 234 | @end 235 | -------------------------------------------------------------------------------- /ZXNavigationBarDemo/ZXNavigationBarDemo/ZXNavigationBar/ZXNavigationBarNavigationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZXNavigationBarNavigationController.m 3 | // ZXNavigationBar 4 | // 5 | // Created by 李兆祥 on 2020/5/29. 6 | // Copyright © 2020 ZXLee. All rights reserved. 7 | // https://github.com/SmileZXLee/ZXNavigationBar 8 | // V1.4.1 9 | 10 | #import "ZXNavigationBarNavigationController.h" 11 | #import 12 | #import "ZXNavigationBarController.h" 13 | #import "ZXNavigationBarTableViewController.h" 14 | @interface ZXNavigationBarNavigationController () 15 | @property (assign, nonatomic) CGFloat touchBeginX; 16 | @property (assign, nonatomic) BOOL doingPopGesture; 17 | @property (strong, nonatomic, nullable) UIViewController *zx_topViewController; 18 | @property (strong, nonatomic) id orgInteractivePopGestureRecognizerDelegate; 19 | @end 20 | 21 | @implementation ZXNavigationBarNavigationController 22 | 23 | - (void)viewDidLoad { 24 | self.orgInteractivePopGestureRecognizerDelegate = self.interactivePopGestureRecognizer.delegate; 25 | [super viewDidLoad]; 26 | self.delegate = self; 27 | self.zx_popGestureCoverRatio = 1; 28 | [self addFullScreenGesture]; 29 | } 30 | 31 | #pragma mark - 重写父类pop和push相关方法 32 | - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{ 33 | if([viewController isKindOfClass:[ZXNavigationBarController class]]){ 34 | self.navigationBarHidden = YES; 35 | } 36 | [self updateTopViewController:viewController]; 37 | if(!self.zx_disableAutoHidesBottomBarWhenPushed){ 38 | [viewController setHidesBottomBarWhenPushed:self.viewControllers.count >= 1]; 39 | } 40 | [super pushViewController:viewController animated:animated]; 41 | } 42 | 43 | - (UIViewController *)popViewControllerAnimated:(BOOL)animated{ 44 | if(self.childViewControllers.count > 1 && !self.doingPopGesture){ 45 | [self updateTopViewController:self.childViewControllers[self.childViewControllers.count - 2]]; 46 | } 47 | return [super popViewControllerAnimated:animated]; 48 | } 49 | 50 | - (NSArray *)popToRootViewControllerAnimated:(BOOL)animated{ 51 | if(self.viewControllers.firstObject && !self.doingPopGesture){ 52 | [self updateTopViewController:self.viewControllers.firstObject]; 53 | } 54 | if(!self.zx_disableAutoHidesBottomBarWhenPushed && self.viewControllers.count > 1){ 55 | self.topViewController.hidesBottomBarWhenPushed = NO; 56 | } 57 | return [super popToRootViewControllerAnimated:animated]; 58 | } 59 | 60 | - (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated{ 61 | if(viewController && !self.doingPopGesture){ 62 | [self updateTopViewController:viewController]; 63 | } 64 | return [super popToViewController:viewController animated:animated]; 65 | } 66 | 67 | #pragma mark - public 68 | - (void)zx_disablePopGesture{ 69 | if(self.zx_popGestureRecognizer){ 70 | [self.view removeGestureRecognizer:self.zx_popGestureRecognizer]; 71 | } 72 | } 73 | 74 | #pragma mark - Private 75 | #pragma mark 添加全屏手势 76 | - (void)addFullScreenGesture{ 77 | self.interactivePopGestureRecognizer.enabled = NO; 78 | UIPanGestureRecognizer *popGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handleNavigationTransition:)]; 79 | popGestureRecognizer.delegate = self; 80 | [self.view addGestureRecognizer:popGestureRecognizer]; 81 | _zx_popGestureRecognizer = popGestureRecognizer; 82 | } 83 | 84 | #pragma mark 处理pop手势 85 | - (void)handleNavigationTransition:(UIPanGestureRecognizer *)panGesture{ 86 | if(self.zx_topViewController && !self.doingPopGesture){ 87 | if([self.zx_topViewController isKindOfClass:[ZXNavigationBarTableViewController class]]){ 88 | ZXNavigationBarTableViewController *topViewController = (ZXNavigationBarTableViewController *)self.zx_topViewController; 89 | if(topViewController.zx_handlePopBlock){ 90 | BOOL shouldPop = topViewController.zx_handlePopBlock((ZXNavigationBarTableViewController *)self.zx_topViewController,ZXNavPopBlockFromPopGesture); 91 | if(!shouldPop){ 92 | return; 93 | } 94 | } 95 | }else{ 96 | ZXNavigationBarController *topViewController = (ZXNavigationBarController *)self.zx_topViewController; 97 | if(topViewController.zx_handlePopBlock){ 98 | BOOL shouldPop = topViewController.zx_handlePopBlock((ZXNavigationBarController *)self.zx_topViewController,ZXNavPopBlockFromPopGesture); 99 | if(!shouldPop){ 100 | return; 101 | } 102 | } 103 | } 104 | 105 | } 106 | if(self.zx_navHandlePopGestureBlock){ 107 | BOOL shouldPop = self.zx_navHandlePopGestureBlock(self.zx_topViewController); 108 | if(!shouldPop){ 109 | return; 110 | } 111 | } 112 | CGFloat panGestureX = [panGesture locationInView:self.view].x; 113 | self.doingPopGesture = YES; 114 | [self.orgInteractivePopGestureRecognizerDelegate performSelector:@selector(handleNavigationTransition:) withObject:panGesture]; 115 | CGFloat popOffsetX = panGestureX - self.touchBeginX; 116 | if(self.zx_handleCustomPopGesture){ 117 | if(panGesture.state == UIGestureRecognizerStateEnded){ 118 | self.doingPopGesture = NO; 119 | if(popOffsetX > self.view.frame.size.width / 2){ 120 | if(@available(iOS 10.0, *)){ 121 | 122 | }else{ 123 | self.zx_handleCustomPopGesture(self.zx_topViewController,1); 124 | } 125 | }else{ 126 | if(@available(iOS 10.0, *)){ 127 | 128 | }else{ 129 | self.zx_handleCustomPopGesture(self.zx_topViewController,0); 130 | } 131 | 132 | } 133 | }else{ 134 | if(popOffsetX >= 0){ 135 | self.zx_handleCustomPopGesture(self.zx_topViewController,(popOffsetX / self.view.frame.size.width)); 136 | }else{ 137 | self.zx_handleCustomPopGesture(self.zx_topViewController,0); 138 | } 139 | } 140 | } 141 | } 142 | 143 | #pragma mark 更新栈顶控制器 144 | - (void)updateTopViewController:(UIViewController *)viewController{ 145 | self.zx_topViewController = nil; 146 | if(viewController && ([viewController isKindOfClass:[ZXNavigationBarController class]] || [viewController isKindOfClass:[ZXNavigationBarTableViewController class]] )){ 147 | if([viewController isKindOfClass:[ZXNavigationBarController class]]){ 148 | self.zx_topViewController = (ZXNavigationBarController *)viewController; 149 | }else{ 150 | self.zx_topViewController = (ZXNavigationBarTableViewController *)viewController; 151 | } 152 | } 153 | } 154 | 155 | #pragma mark - UIGestureRecognizerDelegate 156 | - (BOOL)gestureRecognizerShouldBegin:(UIPanGestureRecognizer *)gestureRecognizer{ 157 | if(gestureRecognizer != self.zx_popGestureRecognizer){ 158 | return YES; 159 | } 160 | if ([[self valueForKey:@"_isTransitioning"] boolValue]) { 161 | return NO; 162 | } 163 | /* **********************************************/ 164 | // Thanks to @forkingdog https://github.com/forkingdog/FDFullscreenPopGesture Respect! 165 | CGPoint translation = [gestureRecognizer translationInView:self.view]; 166 | BOOL isLeftToRight = [UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionLeftToRight; 167 | CGFloat multiplier = isLeftToRight ? 1 : - 1; 168 | if ((translation.x * multiplier) <= 0) { 169 | return NO; 170 | } 171 | /* **********************************************/ 172 | CGFloat panGestureX = [gestureRecognizer locationInView:self.view].x; 173 | CGFloat coverW = self.zx_popGestureCoverRatio * self.view.frame.size.width; 174 | if(panGestureX > coverW){ 175 | return NO; 176 | } 177 | self.touchBeginX = [gestureRecognizer locationInView:self.view].x; 178 | return self.childViewControllers.count != 1; 179 | } 180 | 181 | - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { 182 | BOOL shouldRecognizeSimultaneously = NO; 183 | if(self.zx_popGestureShouldRecognizeSimultaneously){ 184 | shouldRecognizeSimultaneously = self.zx_popGestureShouldRecognizeSimultaneously(otherGestureRecognizer); 185 | } 186 | return shouldRecognizeSimultaneously; 187 | } 188 | 189 | #pragma mark - UINavigationControllerDelegate 190 | - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{ 191 | UIViewController *topViewController = self.topViewController; 192 | if(topViewController){ 193 | id transitionCoordinator = topViewController.transitionCoordinator; 194 | if(transitionCoordinator){ 195 | if(@available(iOS 10.0, *)){ 196 | [transitionCoordinator notifyWhenInteractionChangesUsingBlock:^(id context){ 197 | if([context isCancelled]){ 198 | if(self.zx_handleCustomPopGesture){ 199 | self.zx_handleCustomPopGesture(self.zx_topViewController,0); 200 | } 201 | 202 | }else{ 203 | if(self.zx_handleCustomPopGesture){ 204 | self.zx_handleCustomPopGesture(self.zx_topViewController,1); 205 | } 206 | } 207 | }]; 208 | } 209 | } 210 | } 211 | } 212 | 213 | 214 | #pragma mark - getter&setter 215 | - (void)setZx_disableFullScreenGesture:(BOOL)zx_disableFullScreenGesture{ 216 | _zx_disableFullScreenGesture = zx_disableFullScreenGesture; 217 | if(zx_disableFullScreenGesture){ 218 | self.zx_popGestureCoverRatio = 0.1; 219 | }else{ 220 | self.zx_popGestureCoverRatio = 1; 221 | } 222 | } 223 | 224 | 225 | - (void)setZx_popGestureCoverRatio:(CGFloat)zx_popGestureCoverRatio{ 226 | if(zx_popGestureCoverRatio > 1){ 227 | _zx_popGestureCoverRatio = 1; 228 | }else if(zx_popGestureCoverRatio < 0){ 229 | _zx_popGestureCoverRatio = 0; 230 | }else{ 231 | _zx_popGestureCoverRatio = zx_popGestureCoverRatio; 232 | } 233 | } 234 | @end 235 | --------------------------------------------------------------------------------