CYLTabBarController 第三篇(Tabbar底部栏)

以下笔记内容仅供个人参考,如有理解错误,请高抬贵手,仙人指路,互相学习进步...

使用方法教程

使用方法及教程,查看项目源码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代理来创建按钮实例,并且设置点击按钮的方法处理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容