iOS 自定义tabBarController(中间弧形)
效果图

1.在继承自UITabBarController的自定义controller中调用以下方法(LZCustomTabbar为自定义的tabbar)
- (void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[LZCustomTabbar setTabBarUI:self.tabBar.subviews tabBar:self.tabBar topLineColor:[UIColor lightGrayColor] backgroundColor:self.tabBar.barTintColor];
}
2.UITabBarController的.m文件内容如下
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self initUI];
}
- (void)initUI
{
LZCustomTabbar * tabbar = [[LZCustomTabbar alloc] init];
//中间自定义tabBar点击事件
__weak __typeof(self) weakSelf = self;
tabbar.btnClickBlock = ^(UIButton *btn) {
__typeof(&*weakSelf) strongSelf = weakSelf;
strongSelf.selectedIndex = 4;
};
[self setValue:tabbar forKeyPath:@"tabBar"];
//第一个控制器
ViewController * vc1 = [[ViewController alloc] init];
vc1.view.backgroundColor = [UIColor redColor];
UINavigationController * NC1 = [self addChildVc:vc1 title:@"首页" image:@"tabBar_essence_icon" selectedImage:@"tabBar_essence_click_icon"];
//第2个控制器
UIViewController * vc2 = [[UIViewController alloc] init];
vc2.view.backgroundColor = [UIColor yellowColor];
UINavigationController * NC2 = [self addChildVc:vc2 title:@"课程" image:@"tabBar_new_icon" selectedImage:@"tabBar_new_click_icon"];
//第3个控制器
UIViewController * vc3 = [[UIViewController alloc] init];
vc3.view.backgroundColor = [UIColor blueColor];
UINavigationController * NC3 = [self addChildVc:vc3 title:@"收藏" image:@"tabBar_friendTrends_icon" selectedImage:@"tabBar_friendTrends_click_icon"];
//第4个控制器
UIViewController * vc4 = [[UIViewController alloc] init];
vc4.view.backgroundColor = [UIColor purpleColor];
UINavigationController * NC4 = [self addChildVc:vc4 title:@"我的" image:@"tabBar_me_icon" selectedImage:@"tabBar_me_click_icon"];
//第5个控制器
UIViewController * vc5 = [[UIViewController alloc] init];
vc5.view.backgroundColor = [UIColor whiteColor];
UINavigationController * NC5 = [[UINavigationController alloc] initWithRootViewController:vc5];
self.viewControllers = @[NC1,NC2,NC3,NC4,NC5];
}
#pragma mark - 添加子控制器 设置图片
/**
* 添加一个子控制器
*
* @param childVc 子控制器
* @param title 标题
* @param image 图片
* @param selectedImage 选中的图片
*/
- (UINavigationController*)addChildVc:(UIViewController *)childVc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage
{
// 设置子控制器的文字
childVc.title = title; // 同时设置tabbar和navigationBar的文字
// 设置子控制器的图片
childVc.tabBarItem.image = [[UIImage imageNamed:image] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
childVc.tabBarItem.selectedImage = [[UIImage imageNamed:selectedImage]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
//未选中字体颜色 system为系统字体
[childVc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor lightGrayColor],NSFontAttributeName:[UIFont systemFontOfSize:13]} forState:UIControlStateNormal];
//选中字体颜色
[childVc.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor blackColor],NSFontAttributeName:[UIFont systemFontOfSize:13]} forState:UIControlStateSelected];
// 先给外面传进来的小控制器 包装 一个导航控制器
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:childVc];
return nav;
}
#pragma mark - 类的初始化方法,只有第一次使用类的时候会调用一次该方法
+ (void)initialize
{
//tabbar去掉顶部黑线
[[UITabBar appearance] setBackgroundImage:[UIImage new]];
[[UITabBar appearance] setShadowImage:[UIImage new]];
[[UITabBar appearance] setBarTintColor:[UIColor whiteColor]];
}
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
[LZCustomTabbar setTabBarUI:self.tabBar.subviews tabBar:self.tabBar topLineColor:[UIColor lightGrayColor] backgroundColor:self.tabBar.barTintColor];
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
3.LZCustomTabbar的.m文件内容
@interface LZCustomTabbar ()
@property (nonatomic,weak) UIButton *button;
@end
@implementation LZCustomTabbar
- (UIButton *) button
{
if (_button == nil)
{
UIImage *normalImage = [UIImage originImage:[UIImage imageNamed:@"tabBar_publish_icon"] scaleToSize:CGSizeMake(70, 70)];
UIImage *selectedImage = [UIImage originImage:[UIImage imageNamed:@"tabBar_publish_click_icon"] scaleToSize:CGSizeMake(70, 70)];
UIButton * button = [[UIButton alloc] init];
[button setImage:selectedImage forState:UIControlStateSelected];
[button setImage:normalImage forState:UIControlStateNormal];
[button addTarget:self action:@selector(didBtnAction:) forControlEvents:(UIControlEventTouchUpInside)];
[self addSubview:button];
_button = button;
}
return _button;
}
-(void)didBtnAction:(UIButton*)btn{
if (self.btnClickBlock) {
self.btnClickBlock(btn);
}
}
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setTranslucent:NO];
}
return self;
}
-(void)layoutSubviews
{
[super layoutSubviews];
int index = 0;
CGFloat itemW = self.width/5.0;
for (UIView *subviews in self.subviews)
{
//取到系统tabbar的Item方法
if ([@"UITabBarButton" isEqualToString:NSStringFromClass(subviews.class)])
{
subviews.left = index * itemW;
subviews.width = itemW;
if (index >= 2)
{
subviews.left +=itemW;
}
index++;
}
}
self.button.frame = CGRectMake(0, 0, itemW, itemW);
self.button.center = CGPointMake(self.width/2.0, (self.height - 15 - lz_safeBottomMargin)/2.0);
}
//判断点是否在响应范围
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
if (self.isHidden == NO) {
UIBezierPath *circle = [UIBezierPath bezierPathWithArcCenter:self.button.center radius:35 startAngle:0 endAngle:2* M_PI clockwise:YES];
UIBezierPath *tabbar = [UIBezierPath bezierPathWithRect:self.bounds];
if ( [circle containsPoint:point] || [tabbar containsPoint:point]) {
return YES;
}
return NO;
}else {
return [super pointInside:point withEvent:event];
}
}
+(void)setTabBarUI:(NSArray*)views tabBar:(UITabBar*)tabBar topLineColor:(UIColor*)lineColor backgroundColor:(UIColor*)backgroundColor{
[views enumerateObjectsUsingBlock:^(__kindof UIView * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isKindOfClass:NSClassFromString(@"_UIBarBackground")]) {
NSLog(@"++++++++++%@",@"存在");
if ([obj viewWithTag:999] == nil) {
UIView * top = [[UIView alloc] initWithFrame:CGRectMake(0, -20, tabBar.bounds.size.width, 20)];
top.userInteractionEnabled = NO;
top.backgroundColor = [UIColor clearColor];
top.tag = 999;
[obj addSubview:[[self class] addTopViewToParentView:top topLineColor:lineColor backgroundColor:backgroundColor]];
}
}
}];
}
+(UIView*)addTopViewToParentView:(UIView*)parent topLineColor:(UIColor*)lineColor backgroundColor:(UIColor*)backgroundColor{
////////
//
UIBezierPath *path = [UIBezierPath bezierPath];
//
CGPoint p0 = CGPointMake(0.0, 20);
CGPoint p1 = CGPointMake(parent.bounds.size.width/2.0 - 85, 20);
CGPoint p = CGPointMake(parent.bounds.size.width/2.0, 0);
CGPoint p2 = CGPointMake(parent.bounds.size.width/2.0 + 85, 20);
CGPoint p3 = CGPointMake(parent.bounds.size.width, 20);
//
NSValue *v0 = [NSValue valueWithCGPoint:p0];
NSValue *v1 = [NSValue valueWithCGPoint:p1];
NSValue * v = [NSValue valueWithCGPoint:p];
NSValue *v2 = [NSValue valueWithCGPoint:p2];
NSValue *v3 = [NSValue valueWithCGPoint:p3];
//
NSArray *array = [NSArray arrayWithObjects:v0, v0, v1, v, v2, v3, v3, nil];
//
[path moveToPoint:p0];
//
for (NSInteger i=0; i<array.count - 3; i++) {
CGPoint t0 = [array[i+0] CGPointValue];
CGPoint t1 = [array[i+1] CGPointValue];
CGPoint t2 = [array[i+2] CGPointValue];
CGPoint t3 = [array[i+3] CGPointValue];
//
for (int i=0; i<100; i++) {
CGFloat t = i/100.0;
CGPoint point = [[self class] getPoint:t p0:t0 p1:t1 p2:t2 p3:t3];
[path addLineToPoint:point];
}
}
//
[path addLineToPoint:p3];
//
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.frame = CGRectMake(0.0, 0.0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
shapeLayer.lineWidth = 0.5;
shapeLayer.lineCap = @"round";
shapeLayer.strokeColor = [lineColor CGColor];
shapeLayer.fillColor = [backgroundColor CGColor];
shapeLayer.path = [path CGPath];
shapeLayer.strokeStart = 0.0;
shapeLayer.strokeEnd = 1.0;
[parent.layer addSublayer:shapeLayer];
parent.userInteractionEnabled = NO;
return parent;
}
/**
Catmull-Rom算法
根据四个点计算中间点
*/
+ (CGPoint)getPoint:(CGFloat)t p0:(CGPoint)p0 p1:(CGPoint)p1 p2:(CGPoint)p2 p3:(CGPoint)p3 {
CGFloat t2 = t*t;
CGFloat t3 = t2*t;
CGFloat f0 = -0.5*t3 + t2 - 0.5*t;
CGFloat f1 = 1.5*t3 - 2.5*t2 + 1.0;
CGFloat f2 = -1.5*t3 + 2.0*t2 + 0.5*t;
CGFloat f3 = 0.5*t3 - 0.5*t2;
CGFloat x = p0.x*f0 + p1.x*f1 + p2.x*f2 +p3.x*f3;
CGFloat y = p0.y*f0 + p1.y*f1 + p2.y*f2 +p3.y*f3;
return CGPointMake(x, y);
}
@end
4.下载地址:
https://github.com/liuzhuan155/RadianTabbar或http://code.cocoachina.com/view/1000625
iOS 自定义tabBarController(中间弧形)的更多相关文章
- iOS 自定义TabBarController
转自:http://blog.csdn.net/xn4545945/article/details/35994863 一.自定义的思路 iOS中的TabBarController确实已经很强大了,大部 ...
- 【iOS自定义键盘及键盘切换】详解
[iOS自定义键盘]详解 实现效果展示: 一.实现的协议方法代码 #import <UIKit/UIKit.h> //创建自定义键盘协议 @protocol XFG_KeyBoardDel ...
- Android自定义View 画弧形,文字,并增加动画效果
一个简单的Android自定义View的demo,画弧形,文字,开启一个多线程更新ui界面,在子线程更新ui是不允许的,但是View提供了方法,让我们来了解下吧. 1.封装一个抽象的View类 B ...
- iOS自定义的UISwitch按钮
UISwitch开关控件 开关代替了点选框.开关是到目前为止用起来最简单的控件,不过仍然可以作一定程度的定制化. 一.创建 UISwitch* mySwitch = [[ UISwitchalloc] ...
- 如何实现 iOS 自定义状态栏
给大家介绍如何实现 iOS 自定义状态栏 Sample Code: 01 UIWindow * statusWindow = [[UIWindow alloc] initWithFrame:[UIAp ...
- iOS自定义组与组之间的距离以及视图
iOS自定义组与组之间的距离以及视图 //头视图高度 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(N ...
- iOS 自定义转场动画
代码地址如下:http://www.demodashi.com/demo/12955.html 一.总效果 本文记录分享下自定义转场动画的实现方法,具体到动画效果:新浪微博图集浏览转场效果.手势过渡动 ...
- iOS 自定义转场动画浅谈
代码地址如下:http://www.demodashi.com/demo/11612.html 路漫漫其修远兮,吾将上下而求索 前记 想研究自定义转场动画很久了,时间就像海绵,挤一挤还是有的,花了差不 ...
- iOS自定义转场动画实战讲解
iOS自定义转场动画实战讲解 转场动画这事,说简单也简单,可以通过presentViewController:animated:completion:和dismissViewControllerA ...
随机推荐
- Jmeter(二十八) - 从入门到精通 - Jmeter Http协议录制脚本工具-Badboy1(详解教程)
1.简介 在使用jmeter自动录制脚本时会产生很多无用的请求,所以推荐使用badboy录制脚本之后保存为jmx文件,在jmeter中打开使用.因此宏哥在这里介绍一下Badboy这款工具,本来打算不做 ...
- jmeter多用户登录并发测试
在使用Jmeter进行性能测试时,我们通常会需要配置多个不同用户进行并发测试,这里简单介绍一下配置方法. 1.运行Jmeter.bat, 在打开的测试计划中右键添加一个线程组: 2.在线程组下添加录 ...
- angular11源码探索[DoCheck 生命周期和onChanges区别]
网站 https://blog.thoughtram.io/ https://juristr.com/ https://www.concretepage.com/angular/ https://ww ...
- Java基础教程——缓冲流
缓冲流 "缓冲流"也叫"包装流",是对基本输入输出流的增强: 字节缓冲流: BufferedInputStream , BufferedOutputStream ...
- bypass disable_function
windows 1.com组件绕过 <?php$command=$_POST['a'];$wsh = new COM('WScript.shell'); // 生成一个COM对象 Shell.A ...
- 饱含辛酸开发 WPF CustomControl
引言 不知不觉间WPF开发已有两年光景,或许有很多人会问WPF还需要学习吗?WPF还有前途吗?其实我也很担心这个问题. .Net Core3.x已经支持WPF开发,.Net 5也宣布要支持WPF.是否 ...
- maven依赖问题的出现原因与解决方式
摘要 maven依赖问题作为开发者应该是经常遇到的问题,在个人单独开发单独维护的项目里,可能体现不那么明显,一是自己对导入的jar大部分都很明确,二是出现问题第一解决发现也很快,问题就没那么严重,而在 ...
- 国产开源数据库:腾讯云TBase在分布式HTAP领域的探索与实践
导语 | TBase 是腾讯TEG数据平台团队在开源 PostgreSQL 的基础上研发的企业级分布式 HTAP 数据库系统,可在同一数据库集群中同时为客户提供强一致高并发的分布式在线事务能力以及高 ...
- CSDN-markdown编辑器使用方法
这里写自定义目录标题 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题,有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适合你的列表 创建一 ...
- Model/View开发小结
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 Model/View开发是PyQt和Qt中重要的框架之一,老猿认为另外两个就是信号槽机制和事件机制, ...