diff --git a/CYLTabBarController.podspec b/CYLTabBarController.podspec index 94e99996..8ac1d35f 100644 --- a/CYLTabBarController.podspec +++ b/CYLTabBarController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "CYLTabBarController" - s.version = "1.12.1" + s.version = "1.13.0" s.summary = "Highly customizable tabBar and tabBarController for iOS" s.description = "CYLTabBarController is iPad and iPhone compatible. Supports landscape and portrait orientations and can be used inside UINavigationController." s.homepage = "https://github.com/ChenYilong/CYLTabBarController" diff --git a/CYLTabBarController.xcodeproj/project.pbxproj b/CYLTabBarController.xcodeproj/project.pbxproj index 1ce0ab7c..703ee60a 100644 --- a/CYLTabBarController.xcodeproj/project.pbxproj +++ b/CYLTabBarController.xcodeproj/project.pbxproj @@ -15,6 +15,8 @@ 9A1559DE1CB6D56500CAB1AF /* CYLDetailsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A1559D51CB6D56500CAB1AF /* CYLDetailsViewController.m */; }; 9A1559DF1CB6D56500CAB1AF /* CYLSameCityViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A1559D71CB6D56500CAB1AF /* CYLSameCityViewController.m */; }; 9A1559E41CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A1559E31CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.m */; }; + 9A474B5A1EF03D1B0020D132 /* UITabBarItem+CYLTabBarControllerExtention.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A474B591EF03D1B0020D132 /* UITabBarItem+CYLTabBarControllerExtention.m */; }; + 9A474B5D1EF1586C0020D132 /* UIControl+CYLTabBarControllerExtention.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A474B5C1EF1586C0020D132 /* UIControl+CYLTabBarControllerExtention.m */; }; 9A474C0F1EEFCCE200560ED1 /* UIView+CYLTabBarControllerExtention.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A474C0E1EEFCCE200560ED1 /* UIView+CYLTabBarControllerExtention.m */; }; 9AE667131C800085001DED12 /* UIViewController+CYLTabBarControllerExtention.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AE667121C800085001DED12 /* UIViewController+CYLTabBarControllerExtention.m */; }; 9AE942E71BDC933E00354519 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9AE942CB1BDC933E00354519 /* LaunchScreen.xib */; }; @@ -43,6 +45,10 @@ 9A1559D71CB6D56500CAB1AF /* CYLSameCityViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CYLSameCityViewController.m; sourceTree = ""; }; 9A1559E21CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CYLPlusButtonSubclass.h; sourceTree = ""; }; 9A1559E31CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CYLPlusButtonSubclass.m; sourceTree = ""; }; + 9A474B581EF03D1B0020D132 /* UITabBarItem+CYLTabBarControllerExtention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UITabBarItem+CYLTabBarControllerExtention.h"; sourceTree = ""; }; + 9A474B591EF03D1B0020D132 /* UITabBarItem+CYLTabBarControllerExtention.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UITabBarItem+CYLTabBarControllerExtention.m"; sourceTree = ""; }; + 9A474B5B1EF1586C0020D132 /* UIControl+CYLTabBarControllerExtention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIControl+CYLTabBarControllerExtention.h"; sourceTree = ""; }; + 9A474B5C1EF1586C0020D132 /* UIControl+CYLTabBarControllerExtention.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIControl+CYLTabBarControllerExtention.m"; sourceTree = ""; }; 9A474C0D1EEFCCE200560ED1 /* UIView+CYLTabBarControllerExtention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+CYLTabBarControllerExtention.h"; sourceTree = ""; }; 9A474C0E1EEFCCE200560ED1 /* UIView+CYLTabBarControllerExtention.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+CYLTabBarControllerExtention.m"; sourceTree = ""; }; 9A5B29111D3475BC009E1BEE /* CYLConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CYLConstants.h; sourceTree = ""; }; @@ -207,6 +213,10 @@ 9AE667121C800085001DED12 /* UIViewController+CYLTabBarControllerExtention.m */, 9A474C0D1EEFCCE200560ED1 /* UIView+CYLTabBarControllerExtention.h */, 9A474C0E1EEFCCE200560ED1 /* UIView+CYLTabBarControllerExtention.m */, + 9A474B581EF03D1B0020D132 /* UITabBarItem+CYLTabBarControllerExtention.h */, + 9A474B591EF03D1B0020D132 /* UITabBarItem+CYLTabBarControllerExtention.m */, + 9A474B5B1EF1586C0020D132 /* UIControl+CYLTabBarControllerExtention.h */, + 9A474B5C1EF1586C0020D132 /* UIControl+CYLTabBarControllerExtention.m */, 9A5B29111D3475BC009E1BEE /* CYLConstants.h */, ); path = CYLTabBarController; @@ -290,6 +300,8 @@ 9A1559E41CB6EB1F00CAB1AF /* CYLPlusButtonSubclass.m in Sources */, 9A1559DF1CB6D56500CAB1AF /* CYLSameCityViewController.m in Sources */, 9A1559DB1CB6D56500CAB1AF /* CYLHomeViewController.m in Sources */, + 9A474B5D1EF1586C0020D132 /* UIControl+CYLTabBarControllerExtention.m in Sources */, + 9A474B5A1EF03D1B0020D132 /* UITabBarItem+CYLTabBarControllerExtention.m in Sources */, 9AE942F91BDC937F00354519 /* CYLPlusButton.m in Sources */, 9A1559C81CB6D4D300CAB1AF /* AppDelegate.m in Sources */, 9A474C0F1EEFCCE200560ED1 /* UIView+CYLTabBarControllerExtention.m in Sources */, diff --git a/CYLTabBarController.xcodeproj/project.xcworkspace/xcuserdata/chenyilong.xcuserdatad/UserInterfaceState.xcuserstate b/CYLTabBarController.xcodeproj/project.xcworkspace/xcuserdata/chenyilong.xcuserdatad/UserInterfaceState.xcuserstate index 1c30fc63..bc3c9086 100644 Binary files a/CYLTabBarController.xcodeproj/project.xcworkspace/xcuserdata/chenyilong.xcuserdatad/UserInterfaceState.xcuserstate and b/CYLTabBarController.xcodeproj/project.xcworkspace/xcuserdata/chenyilong.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/CYLTabBarController.xcodeproj/xcuserdata/chenyilong.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/CYLTabBarController.xcodeproj/xcuserdata/chenyilong.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 8b59b1ef..e74390d3 100644 --- a/CYLTabBarController.xcodeproj/xcuserdata/chenyilong.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/CYLTabBarController.xcodeproj/xcuserdata/chenyilong.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -20,11 +20,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "Example/CYLTabBarControllerConfig.m" - timestampString = "518244204.694397" + timestampString = "519049145.117056" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "207" - endingLineNumber = "207" + startingLineNumber = "208" + endingLineNumber = "208" landmarkName = "+imageWithColor:size:" landmarkType = "7"> @@ -36,11 +36,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "CYLTabBarController/CYLTabBarController.m" - timestampString = "518268313.152042" + timestampString = "519062970.556879" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "208" - endingLineNumber = "208" + startingLineNumber = "212" + endingLineNumber = "212" landmarkName = "-setViewControllers:" landmarkType = "7"> @@ -52,11 +52,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "CYLTabBarController/CYLTabBarController.m" - timestampString = "518268313.152042" + timestampString = "519062970.556879" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "206" - endingLineNumber = "206" + startingLineNumber = "210" + endingLineNumber = "210" landmarkName = "-setViewControllers:" landmarkType = "7"> @@ -68,11 +68,11 @@ moduleName = "CYLTabBarController" usesParentBreakpointCondition = "Yes" urlString = "file:///Users/chenyilong/Documents/CYL/CYLTabBarController/CYLTabBarController/CYLTabBarController.m" - timestampString = "519036622.139226" + timestampString = "519137468.917978" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "206" - endingLineNumber = "206" + startingLineNumber = "210" + endingLineNumber = "210" offsetFromSymbolStart = "1380"> @@ -132,11 +132,11 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "CYLTabBarController/CYLTabBarController.m" - timestampString = "518268313.152042" + timestampString = "519062970.556879" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "326" - endingLineNumber = "326" + startingLineNumber = "330" + endingLineNumber = "330" landmarkName = "-tabBarController:shouldSelectViewController:" landmarkType = "7"> @@ -148,30 +148,14 @@ ignoreCount = "0" continueAfterRunningActions = "No" filePath = "CYLTabBarController/CYLTabBarController.m" - timestampString = "518268313.152042" + timestampString = "519062970.556879" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "267" - endingLineNumber = "267" + startingLineNumber = "271" + endingLineNumber = "271" landmarkName = "-getImageFromImageInfo:" landmarkType = "7"> - - - - diff --git a/CYLTabBarController/CYLTabBarController.h b/CYLTabBarController/CYLTabBarController.h index 9ecf2c83..d34d3d98 100644 --- a/CYLTabBarController/CYLTabBarController.h +++ b/CYLTabBarController/CYLTabBarController.h @@ -9,6 +9,11 @@ #import "CYLPlusButton.h" #import "UIViewController+CYLTabBarControllerExtention.h" #import "UIView+CYLTabBarControllerExtention.h" +#import "UITabBarItem+CYLTabBarControllerExtention.h" +#import "UIControl+CYLTabBarControllerExtention.h" + +@class CYLTabBarController; +typedef void(^CYLViewDidLayoutSubViewsBlock)(CYLTabBarController *tabBarController); FOUNDATION_EXTERN NSString *const CYLTabBarItemTitle; FOUNDATION_EXTERN NSString *const CYLTabBarItemImage; @@ -30,6 +35,10 @@ FOUNDATION_EXTERN CGFloat CYLTabBarItemWidth; @interface CYLTabBarController : UITabBarController +@property (nonatomic, copy) CYLViewDidLayoutSubViewsBlock viewDidLayoutSubviewsBlock; + +- (void)setViewDidLayoutSubViewsBlock:(CYLViewDidLayoutSubViewsBlock)viewDidLayoutSubviewsBlock; + /*! * An array of the root view controllers displayed by the tab bar interface. */ diff --git a/CYLTabBarController/CYLTabBarController.m b/CYLTabBarController/CYLTabBarController.m index ced16274..610dcafe 100644 --- a/CYLTabBarController/CYLTabBarController.m +++ b/CYLTabBarController/CYLTabBarController.m @@ -42,7 +42,10 @@ - (void)viewDidLoad { [self.tabBar addObserver:self forKeyPath:@"tabImageViewDefaultOffset" options:NSKeyValueObservingOptionNew context:CYLTabImageViewDefaultOffsetContext]; self.observingTabImageViewDefaultOffset = YES; } - +} + +- (void)setViewDidLayoutSubViewsBlock:(CYLViewDidLayoutSubViewsBlock)viewDidLayoutSubviewsBlock { + _viewDidLayoutSubviewsBlock = viewDidLayoutSubviewsBlock; } //Fix issue #93 @@ -57,6 +60,7 @@ - (void)viewDidLayoutSubviews { [control addTarget:self action:actin forControlEvents:UIControlEventTouchUpInside]; } } + !self.viewDidLayoutSubviewsBlock ?: self.viewDidLayoutSubviewsBlock(self); }); } diff --git a/CYLTabBarController/UIControl+CYLTabBarControllerExtention.h b/CYLTabBarController/UIControl+CYLTabBarControllerExtention.h new file mode 100644 index 00000000..d155a71b --- /dev/null +++ b/CYLTabBarController/UIControl+CYLTabBarControllerExtention.h @@ -0,0 +1,30 @@ +// +// CYLTabBarController.m +// CYLTabBarController +// +// v1.12.0 Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15. +// Copyright © 2015 https://github.com/ChenYilong . All rights reserved. +// + +#import + +@interface UIControl (CYLTabBarControllerExtention) + +- (UIImageView *)cyl_imageView; +- (UIView *)cyl_tabBadgeView; +- (UIImageView *)cyl_tabImageView; +- (UILabel *)cyl_tabLabel; + +/*! + * 调用该方法前已经添加了系统的角标,调用该方法后,系统的角标并未被移除,只是被隐藏,调用 `-cyl_removeTabBadgePoint` 后会重新展示。 + */ +- (void)cyl_showTabBadgePoint; +- (void)cyl_removeTabBadgePoint; +- (BOOL)cyl_isShowTabBadgePoint; +- (void)cyl_setShowTabBadgePoint:(BOOL)showTabBadgePoint; + +@property (nonatomic, strong, setter=cyl_setTabBadgePointView:, getter=cyl_tabBadgePointView) UIView *tabBadgePointView; + +@property (nonatomic, assign, setter=cyl_setTabBadgePointViewOffset:, getter=cyl_tabBadgePointViewOffset) UIOffset tabBadgePointViewOffset; + +@end diff --git a/CYLTabBarController/UIControl+CYLTabBarControllerExtention.m b/CYLTabBarController/UIControl+CYLTabBarControllerExtention.m new file mode 100644 index 00000000..36a02993 --- /dev/null +++ b/CYLTabBarController/UIControl+CYLTabBarControllerExtention.m @@ -0,0 +1,152 @@ +// +// CYLTabBarController.m +// CYLTabBarController +// +// v1.12.0 Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15. +// Copyright © 2015 https://github.com/ChenYilong . All rights reserved. +// + +#import "UIControl+CYLTabBarControllerExtention.h" +#import +#import "UIView+CYLTabBarControllerExtention.h" + +@implementation UIControl (CYLTabBarControllerExtention) + +- (void)cyl_showTabBadgePoint { + [self cyl_setShowTabBadgePoint:YES]; +} + +- (void)cyl_removeTabBadgePoint { + [self cyl_setShowTabBadgePoint:NO]; +} + +- (BOOL)cyl_isShowTabBadgePoint { + return !self.tabBadgePointView.hidden; +} + +- (void)cyl_setShowTabBadgePoint:(BOOL)showTabBadgePoint { + if (showTabBadgePoint && self.tabBadgePointView.superview == nil) { + [self addSubview:self.tabBadgePointView]; + [self bringSubviewToFront:self.tabBadgePointView]; + self.tabBadgePointView.layer.zPosition = MAXFLOAT; + // X + [self addConstraint: + [NSLayoutConstraint constraintWithItem:self.tabBadgePointView //self.cyl_imageView + attribute:NSLayoutAttributeCenterX + relatedBy:0 + toItem:self.cyl_imageView + attribute:NSLayoutAttributeRight + multiplier:1 + constant:self.tabBadgePointViewOffset.horizontal]]; + //Y + [self addConstraint: + [NSLayoutConstraint constraintWithItem:self.tabBadgePointView //self.cyl_imageView + attribute:NSLayoutAttributeCenterY + relatedBy:0 + toItem:self.cyl_imageView + attribute:NSLayoutAttributeTop + multiplier:1 + constant:self.tabBadgePointViewOffset.vertical]]; + } + + self.tabBadgePointView.hidden = showTabBadgePoint == NO; + self.cyl_tabBadgeView.hidden = showTabBadgePoint == YES; +} + +- (void)cyl_setTabBadgePointView:(UIView *)tabBadgePointView { + if (tabBadgePointView.superview) { + [tabBadgePointView removeFromSuperview]; + } + + tabBadgePointView.hidden = YES; + objc_setAssociatedObject(self, @selector(cyl_tabBadgePointView), tabBadgePointView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (UIView *)cyl_tabBadgePointView { + UIView *tabBadgePointView = objc_getAssociatedObject(self, @selector(cyl_tabBadgePointView)); + + if (tabBadgePointView == nil) { + tabBadgePointView = self.cyl_defaultTabBadgePointView; + objc_setAssociatedObject(self, @selector(cyl_tabBadgePointView), tabBadgePointView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); + } + return tabBadgePointView; +} + +- (void)cyl_setTabBadgePointViewOffset:(UIOffset)tabBadgePointViewOffset { + objc_setAssociatedObject(self, @selector(cyl_tabBadgePointViewOffset), [NSValue valueWithUIOffset:tabBadgePointViewOffset], OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +//offset如果都是整数,则往右下偏移 +- (UIOffset)cyl_tabBadgePointViewOffset { + id tabBadgePointViewOffsetObject = objc_getAssociatedObject(self, @selector(cyl_tabBadgePointViewOffset)); + UIOffset tabBadgePointViewOffset = [tabBadgePointViewOffsetObject UIOffsetValue]; + return tabBadgePointViewOffset; +} + +- (UIImageView *)cyl_imageView { + for (UIView *subview in self.subviews) { + if ([subview cyl_isTabImageView]) { + return (UIImageView *)subview; + } + } + return nil; +} + +- (UIView *)cyl_tabBadgeView { + for (UIView *subview in self.subviews) { + if ([subview cyl_isTabBadgeView]) { + return (UIView *)subview; + } + } + return nil; +} + +- (UIImageView *)cyl_tabImageView { + for (UIImageView *subview in self.subviews) { + if ([subview cyl_isTabImageView]) { + return (UIImageView *)subview; + } + } + return nil; +} +- (UILabel *)cyl_tabLabel { + for (UILabel *subview in self.subviews) { + if ([subview cyl_isTabLabel]) { + return (UILabel *)subview; + } + } + return nil; +} + +#pragma mark - private method + +- (UIView *)cyl_defaultTabBadgePointView { + CGFloat const defaultTabBadgePointViewRadius = 4.5; + UIView * defaultTabBadgePointView = [[UIView alloc] init]; + [defaultTabBadgePointView setTranslatesAutoresizingMaskIntoConstraints:NO]; + defaultTabBadgePointView.backgroundColor = [UIColor redColor]; + defaultTabBadgePointView.layer.cornerRadius = defaultTabBadgePointViewRadius; + defaultTabBadgePointView.layer.masksToBounds = YES; + defaultTabBadgePointView.hidden = YES; + // Width constraint + [defaultTabBadgePointView addConstraint:[NSLayoutConstraint constraintWithItem:defaultTabBadgePointView + attribute:NSLayoutAttributeWidth + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute: NSLayoutAttributeNotAnAttribute + multiplier:1 + constant:defaultTabBadgePointViewRadius * 2]]; + + // Height constraint + [defaultTabBadgePointView addConstraint:[NSLayoutConstraint constraintWithItem:defaultTabBadgePointView + attribute:NSLayoutAttributeHeight + relatedBy:NSLayoutRelationEqual + toItem:nil + attribute: NSLayoutAttributeNotAnAttribute + multiplier:1 + constant:defaultTabBadgePointViewRadius * 2]]; + return defaultTabBadgePointView; +} + +@end + diff --git a/CYLTabBarController/UITabBarItem+CYLTabBarControllerExtention.h b/CYLTabBarController/UITabBarItem+CYLTabBarControllerExtention.h new file mode 100755 index 00000000..ffddc298 --- /dev/null +++ b/CYLTabBarController/UITabBarItem+CYLTabBarControllerExtention.h @@ -0,0 +1,15 @@ +// +// CYLTabBarController.m +// CYLTabBarController +// +// v1.12.0 Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15. +// Copyright © 2015 https://github.com/ChenYilong . All rights reserved. +// + +#import + +@interface UITabBarItem (CYLTabBarControllerExtention) + +@property (nonatomic, readonly) UIControl *cyl_tabButton; + +@end diff --git a/CYLTabBarController/UITabBarItem+CYLTabBarControllerExtention.m b/CYLTabBarController/UITabBarItem+CYLTabBarControllerExtention.m new file mode 100755 index 00000000..4d34b760 --- /dev/null +++ b/CYLTabBarController/UITabBarItem+CYLTabBarControllerExtention.m @@ -0,0 +1,57 @@ +// +// CYLTabBarController.m +// CYLTabBarController +// +// v1.12.0 Created by 微博@iOS程序犭袁 ( http://weibo.com/luohanchenyilong/ ) on 10/20/15. +// Copyright © 2015 https://github.com/ChenYilong . All rights reserved. +// + +#import "UITabBarItem+CYLTabBarControllerExtention.h" +#import +#import "UIControl+CYLTabBarControllerExtention.h" + +@implementation UITabBarItem (CYLTabBarControllerExtention) + ++ (void)load { + [self cyl_swizzleRedPacketMethod]; +} + ++ (void)cyl_swizzleRedPacketMethod { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + cyl_ClassMethodSwizzle([self class], @selector(setBadgeValue:), @selector(cyl_setBadgeValue:)); + }); +} + +- (void)cyl_setBadgeValue:(NSString *)badgeValue { + [self.cyl_tabButton cyl_removeTabBadgePoint]; + [self cyl_setBadgeValue:badgeValue]; +} + +- (UIControl *)cyl_tabButton { + UIControl *control = [self valueForKey:@"view"]; + return control; +} + +#pragma mark - private method + +BOOL cyl_ClassMethodSwizzle(Class aClass, SEL originalSelector, SEL swizzleSelector) { + Method originalMethod = class_getInstanceMethod(aClass, originalSelector); + Method swizzleMethod = class_getInstanceMethod(aClass, swizzleSelector); + BOOL didAddMethod = + class_addMethod(aClass, + originalSelector, + method_getImplementation(swizzleMethod), + method_getTypeEncoding(swizzleMethod)); + if (didAddMethod) { + class_replaceMethod(aClass, + swizzleSelector, + method_getImplementation(originalMethod), + method_getTypeEncoding(originalMethod)); + } else { + method_exchangeImplementations(originalMethod, swizzleMethod); + } + return YES; +} + +@end diff --git a/CYLTabBarController/UIView+CYLTabBarControllerExtention.h b/CYLTabBarController/UIView+CYLTabBarControllerExtention.h index 68912204..ba5e70e8 100644 --- a/CYLTabBarController/UIView+CYLTabBarControllerExtention.h +++ b/CYLTabBarController/UIView+CYLTabBarControllerExtention.h @@ -14,5 +14,6 @@ - (BOOL)cyl_isTabButton; - (BOOL)cyl_isTabImageView; - (BOOL)cyl_isTabLabel; +- (BOOL)cyl_isTabBadgeView; @end diff --git a/CYLTabBarController/UIView+CYLTabBarControllerExtention.m b/CYLTabBarController/UIView+CYLTabBarControllerExtention.m index 786dc687..31dac948 100644 --- a/CYLTabBarController/UIView+CYLTabBarControllerExtention.m +++ b/CYLTabBarController/UIView+CYLTabBarControllerExtention.m @@ -27,7 +27,7 @@ - (BOOL)cyl_isTabImageView { return NO; } NSString *subString = [NSString stringWithFormat:@"%@cat%@ew", @"Indi" , @"orVi"]; - BOOL isBackgroundImage = [self cyl_classStringContainsString:subString]; + BOOL isBackgroundImage = [self cyl_classStringhasPrefix:subString]; BOOL isTabImageView = !isBackgroundImage; return isTabImageView; } @@ -37,6 +37,18 @@ - (BOOL)cyl_isTabLabel { return isKindOfLabel; } +- (BOOL)cyl_isTabBadgeView { + BOOL isKindOfClass = [self isKindOfClass:[UIView class]]; + BOOL isClass = [self isMemberOfClass:[UIView class]]; + BOOL isKind = isKindOfClass && !isClass; + if (!isKind) { + return NO; + } + NSString *tabBarClassString = [NSString stringWithFormat:@"%@IB%@", @"_U" , @"adg"]; + BOOL isTabBadgeView = [self cyl_classStringhasPrefix:tabBarClassString];; + return isTabBadgeView; +} + - (BOOL)cyl_isKindOfClass:(Class)class { BOOL isKindOfClass = [self isKindOfClass:class]; BOOL isClass = [self isMemberOfClass:class]; @@ -50,16 +62,13 @@ - (BOOL)cyl_isKindOfClass:(Class)class { - (BOOL)cyl_isTabBarClass { NSString *tabBarClassString = [NSString stringWithFormat:@"U%@a%@ar", @"IT" , @"bB"]; - BOOL isTabBarClass = [self cyl_classStringContainsString:tabBarClassString]; + BOOL isTabBarClass = [self cyl_classStringhasPrefix:tabBarClassString]; return isTabBarClass; } -- (BOOL)cyl_classStringContainsString:(NSString *)subString { +- (BOOL)cyl_classStringhasPrefix:(NSString *)subString { NSString *classString = NSStringFromClass([self class]); - if ([classString rangeOfString:subString].location == NSNotFound) { - return NO; - } - return YES; + return [classString hasPrefix:subString]; } @end diff --git a/CYLTabBarController/UIViewController+CYLTabBarControllerExtention.h b/CYLTabBarController/UIViewController+CYLTabBarControllerExtention.h index 92c06559..9c132138 100644 --- a/CYLTabBarController/UIViewController+CYLTabBarControllerExtention.h +++ b/CYLTabBarController/UIViewController+CYLTabBarControllerExtention.h @@ -20,6 +20,25 @@ typedef void (^CYLPushOrPopCallback)(NSArray<__kindof UIViewController *> *viewC @interface UIViewController (CYLTabBarControllerExtention) +@property (nonatomic, strong, setter=cyl_setTabBadgePointView:, getter=cyl_tabBadgePointView) UIView *tabBadgePointView; + +@property (nonatomic, assign, setter=cyl_setTabBadgePointViewOffset:, getter=cyl_tabBadgePointViewOffset) UIOffset tabBadgePointViewOffset; + +@property (nonatomic, readonly, getter=cyl_isEmbedInTabBarController) BOOL cyl_embedInTabBarController; + +@property (nonatomic, readonly, getter=cyl_tabIndex) NSInteger cyl_tabIndex; + +@property (nonatomic, readonly) UIControl *cyl_tabButton; + +/*! + * 调用该方法前已经添加了系统的角标,调用该方法后,系统的角标并未被移除,只是被隐藏,调用 `-cyl_removeTabBadgePoint` 后会重新展示。 + */ +- (void)cyl_showTabBadgePoint; + +- (void)cyl_removeTabBadgePoint; + +- (BOOL)cyl_isShowTabBadgePoint; + /*! * Pop 到当前 `NavigationController` 的栈底,并改变 `TabBarController` 的 `selectedViewController` 属性,并将被选择的控制器作为返回值返回。 @param index 需要选择的控制器在 `TabBar` 中的 index。 diff --git a/CYLTabBarController/UIViewController+CYLTabBarControllerExtention.m b/CYLTabBarController/UIViewController+CYLTabBarControllerExtention.m index 8d8676ad..f0cf567a 100644 --- a/CYLTabBarController/UIViewController+CYLTabBarControllerExtention.m +++ b/CYLTabBarController/UIViewController+CYLTabBarControllerExtention.m @@ -8,6 +8,7 @@ #import "UIViewController+CYLTabBarControllerExtention.h" #import "CYLTabBarController.h" +#import @implementation UIViewController (CYLTabBarControllerExtention) @@ -103,6 +104,82 @@ - (UIViewController *)cyl_getViewControllerInsteadIOfNavigationController { return self; } + +#pragma mark - public method + +- (void)cyl_showTabBadgePoint { + [self.cyl_tabButton cyl_showTabBadgePoint]; +} + +- (void)cyl_removeTabBadgePoint { + [self.cyl_tabButton cyl_removeTabBadgePoint]; +} + +- (BOOL)cyl_isShowTabBadgePoint { + return [self.cyl_tabButton cyl_isShowTabBadgePoint]; +} + +- (void)cyl_setTabBadgePointView:(UIView *)tabBadgePointView { + [self.cyl_tabButton cyl_setTabBadgePointView:tabBadgePointView]; +} + +- (UIView *)cyl_tabBadgePointView { + return [self.cyl_tabButton cyl_tabBadgePointView];; +} + +- (void)cyl_setTabBadgePointViewOffset:(UIOffset)tabBadgePointViewOffset { + return [self.cyl_tabButton cyl_setTabBadgePointViewOffset:tabBadgePointViewOffset]; +} + +//offset如果都是整数,则往右下偏移 +- (UIOffset)cyl_tabBadgePointViewOffset { + return [self.cyl_tabButton cyl_tabBadgePointViewOffset]; +} + +- (BOOL)cyl_isEmbedInTabBarController { + if (self.cyl_tabBarController == nil) { + return NO; + } + BOOL isEmbedInTabBarController = NO; + for (NSInteger i = 0; i < self.cyl_tabBarController.viewControllers.count; i++) { + UIViewController * vc = self.cyl_tabBarController.viewControllers[i]; + if ([vc cyl_getViewControllerInsteadIOfNavigationController] == [self cyl_getViewControllerInsteadIOfNavigationController]) { + isEmbedInTabBarController = YES; + [self cyl_setTabIndex:i]; + break; + } + } + return isEmbedInTabBarController; +} + +- (void)cyl_setTabIndex:(NSInteger)tabIndex { + objc_setAssociatedObject(self, @selector(cyl_tabIndex), @(tabIndex), OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + +- (NSInteger)cyl_tabIndex { + if (self.cyl_embedInTabBarController == NO) { + return NSNotFound; + } + + id tabIndexObject = objc_getAssociatedObject(self, @selector(cyl_tabIndex)); + NSInteger tabIndex = [tabIndexObject integerValue]; + return tabIndex; +} + +- (UIControl *)cyl_tabButton { + if (self.cyl_embedInTabBarController == NO) { + return nil; + } + UITabBarItem *tabBarItem; + UIControl *control; + @try { + tabBarItem = self.cyl_tabBarController.tabBar.items[self.cyl_tabIndex]; + control = [tabBarItem cyl_tabButton]; + } @catch (NSException *exception) {} + return control; +} + + #pragma mark - #pragma mark - Private Methods diff --git a/Example/AppDelegate.m b/Example/AppDelegate.m index 2ff7d734..062bc2c3 100644 --- a/Example/AppDelegate.m +++ b/Example/AppDelegate.m @@ -26,11 +26,21 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( tabBarControllerConfig.tabBarController.delegate = self; [self.window makeKeyAndVisible]; [self customizeInterface]; + + [tabBarControllerConfig.tabBarController setViewDidLayoutSubViewsBlock:^(CYLTabBarController *tabBarController) { + [tabBarController.viewControllers[1] cyl_showTabBadgePoint]; + + [tabBarController.viewControllers[2] cyl_showTabBadgePoint]; + + [tabBarController.viewControllers[3] cyl_showTabBadgePoint]; + }]; + return YES; } - (void)customizeInterface { [self setUpNavigationBarAppearance]; + } /** @@ -74,17 +84,19 @@ - (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectView } - (void)tabBarController:(UITabBarController *)tabBarController didSelectControl:(UIControl *)control { + if ([[self cyl_tabBarController].selectedViewController cyl_isShowTabBadgePoint]) { + [[self cyl_tabBarController].selectedViewController cyl_removeTabBadgePoint]; + } else { + [[self cyl_tabBarController].selectedViewController cyl_showTabBadgePoint]; + } + UIView *animationView; // 即使 PlusButton 也添加了点击事件,点击 PlusButton 后也会触发该代理方法。 if ([control cyl_isPlusButton]) { UIButton *button = CYLExternPlusButton; animationView = button.imageView; } else if ([control cyl_isTabButton]) { - for (UIView *subView in control.subviews) { - if ([subView cyl_isTabImageView]) { - animationView = subView; - } - } + animationView = [control cyl_tabImageView]; } if ([self cyl_tabBarController].selectedIndex % 2 == 0) { @@ -109,6 +121,8 @@ - (void)addScaleAnimationOnView:(UIView *)animationView { - (void)addRotateAnimationOnView:(UIView *)animationView { // 针对旋转动画,需要将旋转轴向屏幕外侧平移,最大图片宽度的一半 // 否则背景与按钮图片处于同一层次,当按钮图片旋转时,转轴就在背景图上,动画时会有一部分在背景图之下。 + // 动画结束后复位 + CGFloat oldZPosition = animationView.layer.zPosition;//0 animationView.layer.zPosition = 65.f / 2; [UIView animateWithDuration:0.32 delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{ animationView.layer.transform = CATransform3DMakeRotation(M_PI, 0, 1, 0); diff --git a/Example/CYLTabBarControllerConfig.m b/Example/CYLTabBarControllerConfig.m index 511d3b7e..b1d83e85 100644 --- a/Example/CYLTabBarControllerConfig.m +++ b/Example/CYLTabBarControllerConfig.m @@ -7,6 +7,8 @@ // #import "CYLTabBarControllerConfig.h" +static CGFloat const CYLTabBarControllerHeight = 40.f; + @interface CYLBaseNavigationController : UINavigationController @end @@ -125,7 +127,7 @@ - (void)customizeTabBarAppearance:(CYLTabBarController *)tabBarController { #warning CUSTOMIZE YOUR TABBAR APPEARANCE // Customize UITabBar height // 自定义 TabBar 高度 - tabBarController.tabBarHeight = 40.f; +// tabBarController.tabBarHeight = CYLTabBarControllerHeight; // set the text color for unselected state // 普通状态下的文字属性 @@ -187,13 +189,12 @@ - (void)updateTabBarCustomizationWhenTabBarItemWidthDidUpdate { - (void)customizeTabBarSelectionIndicatorImage { ///Get initialized TabBar Height if exists, otherwise get Default TabBar Height. - UITabBarController *tabBarController = [self cyl_tabBarController] ?: [[UITabBarController alloc] init]; - CGFloat tabBarHeight = tabBarController.tabBar.frame.size.height; + CGFloat tabBarHeight = CYLTabBarControllerHeight; CGSize selectionIndicatorImageSize = CGSizeMake(CYLTabBarItemWidth, tabBarHeight); //Get initialized TabBar if exists. UITabBar *tabBar = [self cyl_tabBarController].tabBar ?: [UITabBar appearance]; [tabBar setSelectionIndicatorImage: - [[self class] imageWithColor:[UIColor redColor] + [[self class] imageWithColor:[UIColor yellowColor] size:selectionIndicatorImageSize]]; } diff --git a/README.md b/README.md index d75ddf5b..dedd0303 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,10 @@ 5 | 允许指定加号按钮位置 | 效果如下:

![enter image description here](http://a64.tinypic.com/2mo0h.jpg)

Airbnb-app效果:

![enter image description here](http://a63.tinypic.com/2mgk02v.gif) 6| 支持让 `TabBarItem` 仅显示图标,并自动使图标垂直居中,支持自定义TabBar高度 | 效果可见Airbnb-app效果,或者下图

![enter image description here](https://cloud.githubusercontent.com/assets/7238866/10777333/5d7811c8-7d55-11e5-88be-8cb11bbeaf90.png) 7 | 支持自定义动画 | ![](https://ww1.sinaimg.cn/large/006tNbRwly1fg9hu6qnwbg308v0gctcc.gif) -8 |支持CocoaPods |容易集成 -9 |支持Swift项目导入 | 兼容 -10 |支持横竖屏 | -- +8 | 支持角标自定义View | ![enter image description here](https://ws4.sinaimg.cn/large/006tKfTcly1fgl0yxcaboj30yi06at8t.jpg) +9 |支持CocoaPods |容易集成 +10 |支持Swift项目导入 | 兼容 +11 |支持横竖屏 | --