以下筆記內(nèi)容僅供個人參考,如有理解錯誤,請高抬貴手,仙人指路,互相學(xué)習(xí)進(jìn)步...
使用方法教程
使用方法及教程,查看項(xiàng)目源碼github地址:https://github.com/ChenYilong/CYLTabBarController,非常感謝開源的作者,開源促進(jìn)社區(qū)的發(fā)展,共建和諧社會??!
框架全部文件結(jié)構(gòu)
1.CYLTabBarController
2. CYLTabBar
3.CYLPlusButton
4.UIViewController+CYLTabBarControllerExtention
5.UIView+CYLTabBarControllerExtention
6.UITabBarItem+CYLTabBarControllerExtention
7.UIControl+CYLTabBarControllerExtention
8.CYLConstants
8.總結(jié)
解讀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
/*!
* 用來自定義加號按鈕的位置,如果不實(shí)現(xiàn)默認(rèn)居中。
* @attention 以下兩種情況下,必須實(shí)現(xiàn)該協(xié)議方法,否則 CYLTabBarController 會拋出 exception 來進(jìn)行提示:
1. 添加了 PlusButton 且 TabBarItem 的個數(shù)是奇數(shù)。
2. 實(shí)現(xiàn)了 `+plusChildViewController`。
* @return 用來自定義加號按鈕在 TabBar 中的位置。
*
*/
+ (NSUInteger)indexOfPlusButtonInTabBar;
/*!
* 該方法是為了調(diào)整 PlusButton 中心點(diǎn)Y軸方向的位置,建議在按鈕超出了 tabbar 的邊界時實(shí)現(xiàn)該方法。
* @attention 如果不實(shí)現(xiàn)該方法,內(nèi)部會自動進(jìn)行比對,預(yù)設(shè)一個較為合適的位置,如果實(shí)現(xiàn)了該方法,預(yù)設(shè)的邏輯將失效。
* @return 返回值是自定義按鈕中心點(diǎn)Y軸方向的坐標(biāo)除以 tabbar 的高度,
內(nèi)部實(shí)現(xiàn)時,會使用該返回值來設(shè)置 PlusButton 的 centerY 坐標(biāo),公式如下:
`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 實(shí)現(xiàn)了該方法,但沒有實(shí)現(xiàn) `+multiplierOfTabBarHeight:` 方法,在這種情況下,會在預(yù)設(shè)邏輯的基礎(chǔ)上進(jìn)行偏移。
*/
+ (CGFloat)constantOfPlusButtonCenterYOffsetForTabBarHeight:(CGFloat)tabBarHeight;
/*!
* 實(shí)現(xiàn)該方法后,能讓 PlusButton 的點(diǎn)擊效果與跟點(diǎn)擊其他 TabBar 按鈕效果一樣,跳轉(zhuǎn)到該方法指定的 UIViewController 。
* @attention 必須同時實(shí)現(xiàn) `+indexOfPlusButtonInTabBar` 來指定 PlusButton 的位置。
* @return 指定 PlusButton 點(diǎn)擊后跳轉(zhuǎn)的 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;
//子類執(zhí)行類方法:獲取一個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)]) {
//設(shè)置凸起按鈕的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中實(shí)現(xiàn) `+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 {
//本類,或者不應(yīng)該選擇的情況下,設(shè)置按鈕的選中狀態(tài)為selected,然后return
BOOL notNeedConfigureSelectionStatus = [[self class] respondsToSelector:@selector(shouldSelectPlusChildViewController)] && ![[self class] shouldSelectPlusChildViewController];
if (notNeedConfigureSelectionStatus) {
return;
}
if (sender.selected) {
return;
}
//假如點(diǎn)擊了凸起按鈕,設(shè)置凸起按鈕的選中狀態(tài),并且設(shè)置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];
}
/**
* 按鈕選中狀態(tài)下點(diǎn)擊先顯示normal狀態(tài)的顏色,松開時再回到selected狀態(tài)下顏色。
* 重寫此方法即不會出現(xiàn)上述情況,與 UITabBarButton 相似
*/
- (void)setHighlighted:(BOOL)highlighted {}
@end
CYLPlusButton總結(jié):
1、定義了一個凸起按鈕CYLPlusButton的代理協(xié)議,通過這個代理來初始化按鈕,初始化按鈕跳轉(zhuǎn)的視圖,位置,按鈕高度因子,高度偏移常量。按鈕是否能點(diǎn)擊設(shè)置等
2、自定義了一個CYLPlusButton的UIButton子類, 進(jìn)行注冊一個按鈕,其實(shí)就是通過CYLPlusButton代理來創(chuàng)建按鈕實(shí)例,并且設(shè)置點(diǎn)擊按鈕的方法處理