CYLTabBarController单行代码 Lottie 动画 TabBar

联合创作 · 2023-09-26 15:37

CYLTabBarController 使用一行代码实现 Lottie 动画 TabBar,支持中间带 + 号的 TabBar 样式,自带红点角标,支持动态刷新。


集成后的效果















既支持默认样式 同时也支持创建自定义的形状不规则加号按钮
https://github.com/ChenYilong https://github.com/ChenYilong

支持横竖屏



与其他自定义TabBarController的区别

























































一行代码支持Lottie动画TabBar样式

低耦合,易删除

1、TabBar设置与业务完全分离,最低只需传两个数组即可完成主流App框架搭建。

2、 PlusButton 的所有设置都在单独的一个类( CYLPlusButton 的子类)中实现:删除该特定的类,就能完全将 PlusButton 从项目中删除掉。

TabBar 以及 TabBar 

 TabBarItem 均使用系统原生的控件

因为使用原生的控件,并非 UIButton  UIView 。好处如下:



  • 1. 无需反复调“间距位置等”来接近系统效果。

  • 2. 在push到下一页时 TabBar 的隐藏和显示之间的过渡效果跟系统一致

  • 3. 原生控件,所以可以使用诸多系统API,比如:可以使用 [UITabBar appearance];  [UITabBarItem appearance]; 设置样式。

自动监测是否需要添加“加号”按钮,并能自动设置位置

CYLTabBarController 既支持类似微信的“中规中矩”的 TabBarController 样式,并且默认就是微信这种样式,同时又支持类似“微博”或“淘宝闲鱼”这种具有不规则加号按钮的 TabBarController 

想支持这种样式,只需自定义一个加号按钮,CYLTabBarController 能检测到它的存在并自动将 tabBar 排序好,无需多余操作,并且也预留了一定接口来满足自定义需求。

“加号”按钮的样式、frame 均在自定义的类中独立实现,不会涉及 tabbar 相关设置。

支持动态更新

可动态删除PlusButton ,可以动态更新样式


即使加号按钮超出了tabbar的区域,超出部分依然能响应点击事件

红线内的区域均能响应tabbar相关的点击事件,


允许指定加号按钮位置

Airbnb-app效果:

支持让TabBarItem仅显示图标,并自动使图标垂直居中,支持自定义 TabBar 高度

效果可见 Airbnb-app 效果,或者下图

支持角标自定义View  

支持多 TabBar 嵌套,并指定 PlusButton 位置

 
支持 CocoaPods 容易集成
支持 Swift 项目导入 兼容
支持横竖屏  

项目结构




├── CYLTabBarController #核心库文件夹,如果不使用 CocoaPods 集成,请直接将这个文件夹拖拽带你的项目中
└── Example
└── Classes
   ├── Module #模块类文件夹
│   ├── Home
│   ├── Message
│   ├── Mine
   │   └── SameCity
   └── View #这里放着 CYLPlusButton 的子类 CYLPlusButtonSubclass,演示了如何创建自定义的形状不规则加号按钮

使用 CYLTabBarController


四步完成主流App框架搭建:



  1. 第一步:使用CocoaPods导入CYLTabBarController

  2. 第二步:设置CYLTabBarController的两个数组:控制器数组和TabBar属性数组

  3. 第三步:将CYLTabBarController设置为window的RootViewController

  4. 第四步(可选):创建自定义的形状不规则加号按钮


第一步:使用 CocoaPods 导入 CYLTabBarController



  1. CocoaPods 安装


  如果您的机器上已经安装了 CocoaPods,直接进入下一步即可。


  如果您的网络已经翻墙,在终端中运行如下命令直接安装:


    sudo gem install cocoapods  


  如果您的网络不能翻墙,可以通过国内 Ruby China 的 RubyGems 镜像进行安装。


  在终端依次运行以下命令:


    gem sources --add https://gems.ruby-china.com/ --remove https://rubygems.org/     sudo gem install cocoapods  



  1. 查询 CocoaPods 源中的本库


  在终端中运行以下命令:


    pod search CYLTabBarController  


   这里注意,这个命令搜索的是本机上的最新版本,并没有联网查询。如果运行以上命令,没有搜到或者搜不到最新版本,您可以运行以下命令,更新一下您本地的 CocoaPods 源列表。


    pod repo update  



  1. 使用 CocoaPods 导入


  打开终端,进入到您的工程目录,执行以下命令,会自动生成一个 Podfile 文件。


    pod init  


  然后使用 CocoaPods 进行安装。如果尚未安装 CocoaPods,运行以下命令进行安装:




gem install cocoapods


  打开 Podfile,在您项目的 target 下加入以下内容。(此处示例可能是旧版本,使用时请替换为最新版,最新版信息可以从这里获取:


  在文件 Podfile 中加入以下内容:




pod 'CYLTabBarController', '~> 1.24.0'


  然后在终端中运行以下命令:




pod install


  或者这个命令:




# 禁止升级 CocoaPods 的 spec 仓库,否则会卡在 Analyzing dependencies,非常慢
pod update --verbose --no-repo-update


  如果提示找不到库,则可去掉 --no-repo-update


  完成后1.24.0,CocoaPods 会在您的工程根目录下生成一个 .xcworkspace 文件。您需要通过此文件打开您的工程,而不是之前的 .xcodeproj


CocoaPods 使用说明


指定 CYLTabBarController 版本


CocoaPods 中,有几种设置 CYLTabBarController 版本的方法。如:


>= 1.n.X 会根据您本地的 CocoaPods 源列表,导入不低于 1.(n+1).X 版本的 CYLTabBarController。


~> 1.n.X 会根据您本地的 CocoaPods 源列表,介于 1.n.X~1.(n+1).0 之前版本的 CYLTabBarController。


建议选择后者:锁定版本,便于团队开发。如:


(此处示例可能是旧版本,使用时请替换为最新版,最新版信息可以从这里获取:




pod 'CYLTabBarController', '~> 1.24.0'



  • 升级本地 CocoaPods 源


  `CocoaPods 有一个中心化的源,默认本地会缓存 CocoaPods 源服务器上的所有 CYLTabBarController 版本。


如果搜索的时候没有搜到或者搜不到最新版本,可以执行以下命令更新一下本地的缓存。




pod repo update



  • 升级工程的 CYLTabBarController 版本


更新您工程目录中 Podfile 指定的 CYLTabBarController 版本后,在终端中执行以下命令。




pod update



  • 清除 Cocoapods 本地缓存


特殊情况下,由于网络或者别的原因,通过 CocoaPods 下载的文件可能会有问题。


这时候您可以删除 CocoaPods 的缓存(~/Library/Caches/CocoaPods/Pods/Release 目录),再次导入即可。



  • 查看当前使用的 CYLTabBarController 版本


您可以在 Podfile.lock 文件中看到您工程中使用的 CYLTabBarController 版本。


关于 CocoaPods 的更多内容,您可以参考 CocoaPods 文档


第二步:设置 CYLTabBarController 的两个数组:控制器数组和 TabBar 属性数组




//MainTabBarController

@interface MainTabBarController : CYLTabBarController
@end


- (instancetype)init {
if (!(self = [super init])) {
return nil;
}
/**
* 以下两行代码目的在于手动设置让TabBarItem只显示图标,不显示文字,并让图标垂直居中。
* 等效于在 `-tabBarItemsAttributesForController` 方法中不传 `CYLTabBarItemTitle` 字段。
* 更推荐后一种做法。
*/
UIEdgeInsets imageInsets = UIEdgeInsetsZero;//UIEdgeInsetsMake(4.5, 0, -4.5, 0);
UIOffset titlePositionAdjustment = UIOffsetMake(0, -3.5);
CYLTabBarController *tabBarController = [CYLTabBarController tabBarControllerWithViewControllers:self.viewControllers
tabBarItemsAttributes:self.tabBarItemsAttributesForController
imageInsets:imageInsets
titlePositionAdjustment:titlePositionAdjustment
context:nil
];
[self customizeTabBarAppearance:tabBarController];
self.navigationController.navigationBar.hidden = YES;
return (self = (MainTabBarController *)tabBarController);
}

- (NSArray *)viewControllers {
CYLHomeViewController *firstViewController = [[CYLHomeViewController alloc] init];
UIViewController *firstNavigationController = [[CYLBaseNavigationController alloc]
initWithRootViewController:firstViewController];
[firstViewController cyl_setHideNavigationBarSeparator:YES];
CYLSameCityViewController *secondViewController = [[CYLSameCityViewController alloc] init];
UIViewController *secondNavigationController = [[CYLBaseNavigationController alloc]
initWithRootViewController:secondViewController];
[secondViewController cyl_setHideNavigationBarSeparator:YES];
NSArray *viewControllers = @[
firstNavigationController,
secondNavigationController,
];
return viewControllers;
}

- (NSArray *)tabBarItemsAttributesForController {
NSDictionary *firstTabBarItemsAttributes = @{
CYLTabBarItemTitle : @"首页",
CYLTabBarItemImage : self.darkMode ? @"home_highlight" : @"home_normal", /* NSString and UIImage are supported*/
CYLTabBarItemSelectedImage : @"home_highlight", /* NSString and UIImage are supported*/
};
NSDictionary *secondTabBarItemsAttributes = @{
CYLTabBarItemTitle : @"鱼塘",
CYLTabBarItemImage : self.darkMode ? @"fishpond_highlight" : @"fishpond_normal",
CYLTabBarItemSelectedImage : @"fishpond_highlight",
};


NSArray *tabBarItemsAttributes = @[
firstTabBarItemsAttributes,
secondTabBarItemsAttributes,
];
return tabBarItemsAttributes;
}


在这个字典中,CYLTabBarItemImage  CYLTabBarItemSelectedImage 支持 NSStringUIImage 两种格式。CYLTabBarItemTitle 不设置将只展示图标,并会对布局作出居中处理。


第三步:将 CYLTabBarController 设置为 window 的 RootViewController




- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/* *省略部分: * */
[self.window setRootViewController:self.tabBarController];
/* *省略部分: * */
return YES;
}


或者将 CYLTabBarController 的子类设为 RootViewCOntroller ,也可以将CYLTabBarController子类的 NavigationViewController 作为 RootViewCOntroller,方便动态更新,Demo 中就是采用后者。


第四步(可选):创建自定义的形状不规则加号按钮


创建一个继承于 CYLPlusButton 的类,要求和步骤:



  1. 实现 CYLPlusButtonSubclassing 协议


  2. 子类将自身类型进行注册:调用 [YourClass registerPlusButton],需要在 RootViewCOntroller 的 ViewDidLoad 中注册,也可以在 -application:didFinishLaunchingWithOptions: 方法里面操作。



这里注意,不建议在子类的 +load 方法中调用,比如像下面这样做,在 iOS10 系统上有 Crash 的风险:




+ (void)load {
[super registerPlusButton];
}


协议提供了可选方法:




+ (NSUInteger)indexOfPlusButtonInTabBar;
+ (CGFloat)multiplierOfTabBarHeight:(CGFloat)tabBarHeight;
+ (UIViewController *)plusChildViewController;
+ (BOOL)shouldSelectPlusChildViewController;


作用分别是:




+ (NSUInteger)indexOfPlusButtonInTabBar;


用来自定义加号按钮的位置,如果不实现默认居中,但是如果 tabbar 的个数是奇数则必须实现该方法,否则 CYLTabBarController 会抛出 exception 来进行提示。


主要适用于如下情景:




Airbnb-app效果:





+ (CGFloat)multiplierOfTabBarHeight:(CGFloat)tabBarHeight;


该方法是为了调整自定义按钮中心点Y轴方向的位置,建议在按钮超出了 tabbar 的边界时实现该方法。返回值是自定义按钮中心点Y轴方向的坐标除以 tabbar 的高度,如果不实现,会自动进行比对,预设一个较为合适的位置,如果实现了该方法,预设的逻辑将失效。


内部实现时,会使用该返回值来设置 PlusButton 的 centerY 坐标,公式如下:


PlusButtonCenterY = multiplierOfTabBarHeight * taBarHeight + constantOfPlusButtonCenterYOffset;


也就是说:如果 constantOfPlusButtonCenterYOffset 为0,同时 multiplierOfTabBarHeight 的值是0.5,表示 PlusButton 居中,小于0.5表示 PlusButton 偏上,大于0.5则表示偏下。




+ (CGFloat)constantOfPlusButtonCenterYOffsetForTabBarHeight:(CGFloat)tabBarHeight;


参考 +multiplierOfTabBarHeight: 中的公式:


PlusButtonCenterY = multiplierOfTabBarHeight * taBarHeight + constantOfPlusButtonCenterYOffset;


也就是说: constantOfPlusButtonCenterYOffset 大于0会向下偏移,小于0会向上偏移。


注意:实现了该方法,但没有实现 +multiplierOfTabBarHeight: 方法,在这种情况下,会在预设逻辑的基础上进行偏移。


详见Demo中的 CYLPlusButtonSubclass 类的实现。




+ (UIViewController *)plusChildViewController;


详见: 点击 PlusButton 跳转到指定 UIViewController


另外,如果加号按钮超出了边界,一般需要手动调用如下代码取消 tabbar 顶部默认的阴影,可在 AppDelegate 类中调用:




//去除 TabBar 自带的顶部阴影
[[UITabBar appearance] setShadowImage:[[UIImage alloc] init]];


// iOS10 后 需要使用 -[CYLTabBarController hideTabBarShadowImageView] 见 AppDelegate 类中的演示;


如何调整、自定义 PlusButton 与其它 TabBarItem 的宽度?


CYLTabBarController 规定:




TabBarItem 宽度 = ( TabBar 总宽度 - PlusButton 宽度 ) / (TabBarItem 个数)


所以想自定义宽度,只需要修改 PlusButton 的宽度即可。


比如你就可以在 Demo中的 CYLPlusButtonSubclass.m 类里:





[button sizeToFit];


改为




button.frame = CGRectMake(0.0, 0.0, 250, 100);
button.backgroundColor = [UIColor redColor];


效果如下, 1.24.0


同时你也可以顺便测试下 CYLTabBarController 的这一个特性:



即使加号按钮超出了tabbar的区域,超出部分依然能响应点击事件



并且你可以在项目中的任意位置读取到 PlusButton 的宽度,借助 CYLTabBarController.h 定义的 CYLPlusButtonWidth 这个extern。可参考 +[CYLTabBarControllerConfig customizeTabBarAppearance:] 里的用法。


 

浏览 22
点赞
评论
收藏
分享

手机扫一扫分享

编辑 分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

编辑 分享
举报