以下笔记内容仅供个人参考,如有理解错误,请高抬贵手,仙人指路,互相学习进步...
使用方法教程
使用方法及教程,查看项目源码github地址:https://github.com/ChenYilong/CYLTabBarController,非常感谢开源的作者,开源促进社区的发展,共建和谐社会😆!
框架全部文件结构
1.CYLTabBarController
2. CYLTabBar
3.CYLPlusButton
4.UIViewController+CYLTabBarControllerExtention
5.UIView+CYLTabBarControllerExtention
6.UITabBarItem+CYLTabBarControllerExtention
7.UIControl+CYLTabBarControllerExtention
8.CYLConstants
8.总结
解读CYLPlusButton类文件,在源码中中文注释自己的理解👇
CYLPlusButton类文件(.h,.m)
解读CYLPlusButton.h, CYLPlusButton.m
CYLPlusButton.h文件
#import <UIKit/UIKit.h>
#import "CYLConstants.h"
@class CYLPlusButton;
@protocol CYLPlusButtonSubclassing
@required
+ (id)plusButton;
@optional
/*!
* 用来自定义加号按钮的位置,如果不实现默认居中。
* @attention 以下两种情况下,必须实现该协议方法,否则 CYLTabBarController 会抛出 exception 来进行提示:
1. 添加了 PlusButton 且 TabBarItem 的个数是奇数。
2. 实现了 `+plusChildViewController`。
* @return 用来自定义加号按钮在 TabBar 中的位置。
*
*/
+ (NSUInteger)indexOfPlusButtonInTabBar;
/*!
* 该方法是为了调整 PlusButton 中心点Y轴方向的位置,建议在按钮超出了 tabbar 的边界时实现该方法。
* @attention 如果不实现该方法,内部会自动进行比对,预设一个较为合适的位置,如果实现了该方法,预设的逻辑将失效。
* @return 返回值是自定义按钮中心点Y轴方向的坐标除以 tabbar 的高度,
内部实现时,会使用该返回值来设置 PlusButton 的 centerY 坐标,公式如下:
`PlusButtonCenterY = multiplierOfTabBarHeight * taBarHeight + constantOfPlusButtonCenterYOffset;`
也就是说:如果 constantOfPlusButtonCenterYOffset 为0,同时 multiplierOfTabBarHeight 的值是0.5,表示 PlusButton 居中,小于0.5表示 PlusButton 偏上,大于0.5则表示偏下。
*
*/
+ (CGFloat)multiplierOfTabBarHeight:(CGFloat)tabBarHeight;
/*!
* 见 `+multiplierOfTabBarHeight:` 注释:
* `PlusButtonCenterY = multiplierOfTabBarHeight * taBarHeight + constantOfPlusButtonCenterYOffset;`
* 也就是说: constantOfPlusButtonCenterYOffset 大于0会向下偏移,小于0会向上偏移。
* @attention 实现了该方法,但没有实现 `+multiplierOfTabBarHeight:` 方法,在这种情况下,会在预设逻辑的基础上进行偏移。
*/
+ (CGFloat)constantOfPlusButtonCenterYOffsetForTabBarHeight:(CGFloat)tabBarHeight;
/*!
* 实现该方法后,能让 PlusButton 的点击效果与跟点击其他 TabBar 按钮效果一样,跳转到该方法指定的 UIViewController 。
* @attention 必须同时实现 `+indexOfPlusButtonInTabBar` 来指定 PlusButton 的位置。
* @return 指定 PlusButton 点击后跳转的 UIViewController。
*
*/
+ (UIViewController *)plusChildViewController;
/*!
*
Asks the delegate whether the specified view controller should be made active.
Return YES if the view controller’s tab should be selected or NO if the current tab should remain active.
Returns YES true if the view controller’s tab should be selected or
NO false if the current tab should remain active.
*/
+ (BOOL)shouldSelectPlusChildViewController;
#pragma mark - Deprecated API
+ (CGFloat)multiplerInCenterY CYL_DEPRECATED("Deprecated in 1.6.0. Use `+multiplierOfTabBarHeight:` instead.");
@end
@class CYLTabBar;
FOUNDATION_EXTERN UIButton<CYLPlusButtonSubclassing> *CYLExternPlusButton;
FOUNDATION_EXTERN UIViewController *CYLPlusChildViewController;
@interface CYLPlusButton : UIButton
+ (void)registerPlusButton;
- (void)plusChildViewControllerButtonClicked:(UIButton<CYLPlusButtonSubclassing> *)sender;
@end
#pragma mark - Deprecated API
@interface CYLPlusButton (CYLDeprecated)
+ (void)registerSubclass CYL_DEPRECATED("Deprecated in 1.6.0. Use `+[CYLPlusButton registerPlusButton]` instead.");
@end
CYLPlusButton.m
#import "CYLPlusButton.h"
#import "CYLTabBarController.h"
CGFloat CYLPlusButtonWidth = 0.0f;
UIButton<CYLPlusButtonSubclassing> *CYLExternPlusButton = nil;
UIViewController *CYLPlusChildViewController = nil;
@implementation CYLPlusButton
#pragma mark -
#pragma mark - public Methods
//获取按钮,添加事件
+ (void)registerPlusButton {
if (![self conformsToProtocol:@protocol(CYLPlusButtonSubclassing)]) {
return;
}
//继承CYLPlusButton的子类
Class<CYLPlusButtonSubclassing> class = self;
//子类执行类方法:获取一个plusButton按钮
UIButton<CYLPlusButtonSubclassing> *plusButton = [class plusButton];
CYLExternPlusButton = plusButton;
CYLPlusButtonWidth = plusButton.frame.size.width;
if ([[self class] respondsToSelector:@selector(plusChildViewController)]) {
CYLPlusChildViewController = [class plusChildViewController];
//添加事件方法
[[self class] addSelectViewControllerTarget:plusButton];
if ([[self class] respondsToSelector:@selector(indexOfPlusButtonInTabBar)]) {
//设置凸起按钮的index位置
CYLPlusButtonIndex = [[self class] indexOfPlusButtonInTabBar];
} else {
[NSException raise:@"CYLTabBarController" format:@"If you want to add PlusChildViewController, you must realizse `+indexOfPlusButtonInTabBar` in your custom plusButton class.【Chinese】如果你想使用PlusChildViewController样式,你必须同时在你自定义的plusButton中实现 `+indexOfPlusButtonInTabBar`,来指定plusButton的位置"];
}
}
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ (void)registerSubclass {
[self registerPlusButton];
}
#pragma clang diagnostic pop
- (void)plusChildViewControllerButtonClicked:(UIButton<CYLPlusButtonSubclassing> *)sender {
//本类,或者不应该选择的情况下,设置按钮的选中状态为selected,然后return
BOOL notNeedConfigureSelectionStatus = [[self class] respondsToSelector:@selector(shouldSelectPlusChildViewController)] && ![[self class] shouldSelectPlusChildViewController];
if (notNeedConfigureSelectionStatus) {
return;
}
if (sender.selected) {
return;
}
//假如点击了凸起按钮,设置凸起按钮的选中状态,并且设置tabbarcontroller的选中位置
sender.selected = YES;
[self cyl_tabBarController].selectedIndex = CYLPlusButtonIndex;
}
#pragma mark -
#pragma mark - Private Methods
+ (void)addSelectViewControllerTarget:(UIButton<CYLPlusButtonSubclassing> *)plusButton {
//获取plusButton在target中的所有事件方法名称
id target = self;
NSArray<NSString *> *selectorNamesArray = [plusButton actionsForTarget:target forControlEvent:UIControlEventTouchUpInside];
if (selectorNamesArray.count == 0) {
target = plusButton;
selectorNamesArray = [plusButton actionsForTarget:target forControlEvent:UIControlEventTouchUpInside];
}
//遍历移除所有的事件方法
[selectorNamesArray enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
SEL selector = NSSelectorFromString(obj);
[plusButton removeTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
}];
//从新添加事件方法
[plusButton addTarget:plusButton action:@selector(plusChildViewControllerButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
}
/**
* 按钮选中状态下点击先显示normal状态的颜色,松开时再回到selected状态下颜色。
* 重写此方法即不会出现上述情况,与 UITabBarButton 相似
*/
- (void)setHighlighted:(BOOL)highlighted {}
@end
CYLPlusButton总结:
1、定义了一个凸起按钮CYLPlusButton的代理协议,通过这个代理来初始化按钮,初始化按钮跳转的视图,位置,按钮高度因子,高度偏移常量。按钮是否能点击设置等
2、自定义了一个CYLPlusButton的UIButton子类, 进行注册一个按钮,其实就是通过CYLPlusButton代理来创建按钮实例,并且设置点击按钮的方法处理