IOS实现中间凸起圆形TabBar

  中间凸起的圆形TabBar曾经比较流行,类似于闲鱼之类的APP就使用了中间凸起TabBar,这两天自己动手实现了一个,效果图如下:

  大致原理:重写UITabBar和UITabBarController,在UITabBar中枚举所有的UITabBarButton类型子控件,重新设置子控件的位置,为中间的圆形按钮预留位置,在layoutsubviews中添加圆形按钮并且重写hitTest方法,判断触摸是否位于圆形按钮区域,如果是,则通过圆形按钮响应点击事件。在UITabBarController我们需要用我们自己创建的UITabBar去替换系统原来的UITabBar,在创建UITabBarController的时候也需要用我们自己创建的UITabBarController。

  代码如下:

  MyUITabBar.m

#import "MyUITabBar.h"
#import "RoundButtonViewController.h"
#import "MyUITabBarController.h"

@interface MyUITabBarController ()

@end

@implementation MyUITabBarController

- (void)viewDidLoad {
    [super viewDidLoad];
    MyUITabBar *tabbar = [[MyUITabBar alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
    tabbar.myDelegate = self;
    //修改系统的Tabbar,使用我们自定义的Tabbar
    [self setValue:tabbar forKeyPath:@"tabBar"];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)RoundButtonClicked
{
    RoundButtonViewController *roundButtonViewController = [[RoundButtonViewController alloc] init];
    roundButtonViewController.view.backgroundColor = [UIColor blueColor];
    UINavigationController *navVc = [[UINavigationController alloc] initWithRootViewController:roundButtonViewController];
    [self presentViewController:navVc animated:YES completion:nil];
}
/*
#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

  MyUITabBar.h

#import <UIKit/UIKit.h>

@protocol RoundButtonDelegate <NSObject>

- (void)RoundButtonClicked;

@end

@interface MyUITabBar : UITabBar<RoundButtonDelegate>

@property (nonatomic, weak) id <RoundButtonDelegate>myDelegate;

@property (nonatomic, strong)UIButton *roundButton;

@end

  MyUITabBar.m

#import "MyUITabBar.h"

@implementation MyUITabBar

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

- (instancetype) initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        self.roundButton.frame = frame;
        self.backgroundColor = [UIColor whiteColor];
        [self.roundButton setBackgroundImage:[UIImage imageNamed:@"roundbutton" ] forState:UIControlStateNormal];
        [self.roundButton addTarget:self action:@selector(roundBtnClicked) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:self.roundButton];
    }
    return self;
}

//懒加载
- (UIButton *)roundButton
{
    if (!_roundButton) {
        _roundButton = [[UIButton alloc] init];
    }
    return _roundButton;
}

- (void)roundBtnClicked{
    if ([self.myDelegate respondsToSelector:@selector(RoundButtonClicked)]) {
        [self.myDelegate RoundButtonClicked];
    }
}

- (void)layoutSubviews{
    int centerx = self.bounds.size.width * 0.5;
    int centery = self.bounds.size.height * 0.5;
    self.roundButton.frame = CGRectMake(centerx - 30, centery - 50, 60, 60);

    Class class = NSClassFromString(@"UITabBarButton");
    int index = 0;
    int tabWidth = self.bounds.size.width / 3.0;

    for (UIView *view in self.subviews) {
        //找到UITabBarButton类型子控件
        if ([view isKindOfClass:class]) {
            CGRect rect = view.frame;
            rect.origin.x = index * tabWidth;
            rect.size.width = tabWidth;
            view.frame = rect;
            index++;
            //留出位置放置中间凸出按钮
            if (index == 1) {
                index++;
            }

        }
    }
}

//响应触摸事件,如果触摸位置位于圆形按钮控件上,则由圆形按钮处理触摸消息
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    //判断tabbar是否隐藏
    if (self.hidden == NO) {
        if ([self touchPointInsideCircle:self.roundButton.center radius:30 targetPoint:point]) {
            //如果位于圆形按钮上,则由圆形按钮处理触摸消息
            return self.roundButton;
        }
        else{
            //否则系统默认处理
            return [super hitTest:point withEvent:event];
        }
    }
    return [super hitTest:point withEvent:event];
}

- (BOOL)touchPointInsideCircle:(CGPoint)center radius:(CGFloat)radius targetPoint:(CGPoint)point
{
    CGFloat dist = sqrtf((point.x - center.x) * (point.x - center.x) +
                         (point.y - center.y) * (point.y - center.y));
    return (dist <= radius);
}

@end

  RoundButtonViewController.m

#import "RoundButtonViewController.h"

@interface RoundButtonViewController ()

@end

@implementation RoundButtonViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view setBackgroundColor:[UIColor blueColor]];

    [self setUpNav];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)setUpNav
{
    UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back"] style:UIBarButtonItemStyleDone target:self action:@selector(pop)];

    [backItem setBackgroundImage:[UIImage imageNamed:@"back_clicked"] forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];

    self.navigationItem.leftBarButtonItem = backItem;
    self.navigationItem.title = @"12345";

}

- (void)pop
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

/*
#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

  AppDelegate.m

#import "AppDelegate.h"
#import "TabViewController1.h"
#import "TabViewController2.h"
#import "MyUITabBarController.h"
@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    MyUITabBarController *myUITabBarController=[[MyUITabBarController alloc]init];
    self.window.rootViewController=myUITabBarController;

    NSDictionary *attributes = @{ NSForegroundColorAttributeName : [UIColor colorWithRed:0x33 / 255.0 green:0x33 / 255.0 blue:0x33 / 255.0 alpha:1],NSFontAttributeName : [UIFont systemFontOfSize:10]};
    [[UITabBarItem appearance] setTitleTextAttributes:attributes forState:UIControlStateNormal];

    NSDictionary *attributesSelected = @{ NSForegroundColorAttributeName : [UIColor colorWithRed:0xec / 255.0 green:0x48 / 255.0 blue:0x28 / 255.0 alpha:1],NSFontAttributeName : [UIFont systemFontOfSize:10]};
    [[UITabBarItem appearance] setTitleTextAttributes:attributesSelected forState:UIControlStateSelected];

    UIImage *normalImage = [[UIImage imageNamed:@"tab1"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    UIImage *selectImage = [[UIImage imageNamed:@"tab1_selected"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    UITabBarItem *tabBarItem = [[UITabBarItem alloc]initWithTitle:@"tab1" image:normalImage selectedImage:selectImage];
    tabBarItem.titlePositionAdjustment = UIOffsetMake(0.f, -3.f);
    TabViewController1 *tabViewController1 = [[TabViewController1 alloc] init];
    tabViewController1.tabBarItem = tabBarItem;

    normalImage = [[UIImage imageNamed:@"tab2"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    selectImage = [[UIImage imageNamed:@"tab2_selected"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    tabBarItem = [[UITabBarItem alloc] initWithTitle:@"tab2" image:normalImage selectedImage:selectImage];
    TabViewController2 *tabViewController2 = [[TabViewController2 alloc] init];
    tabViewController2.tabBarItem = tabBarItem;

    myUITabBarController.viewControllers=@[tabViewController1,tabViewController2];
    [self.window makeKeyAndVisible];

    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end

   部分头文件和TabViewController1、TabViewController2的文件没有放上来,因为这里面没有添加任何自己的代码。源码下载链接:http://download.csdn.net/detail/lzm2625347497/9571511

时间: 2024-09-29 03:29:39

IOS实现中间凸起圆形TabBar的相关文章

IOS把图片做成圆形效果

利用CAShapeLayer可以制作出任意的几何图形,把它作为UIImageView的遮罩,达到把图片做成圆形效果. imgView = [[UIImageView alloc]initWithFrame:CGRectMake(10, 35, 80, 80)]; imgView.image = [UIImage imageNamed:@"ma.jpg"]; UIBezierPath* path = [UIBezierPath bezierPathWithArcCenter:CGPoin

ios定制中间突出的tabBar

我觉得有两个思路,一个是自己写tabBar  通过自定义实现,缺点呢就是比较麻烦,优点就是代码比较清楚,而且比较稳定. 另一个思路就是写个大按钮加在tabBar上 通过监听tabitem的点击来实现相似的效果,其实这只是一个障眼法(具体实现可以参照下面链接),优点呢,就是比较简单,不用自己自定义控件,缺点呢就是太不方便了  有时候我们需要隐藏tabBar,但是这个按钮是独立的,不会随着tabBar消失而消失,需要我们自己手动去控制,页面少还行,页面多更复杂,个人不推荐这种方法.建议自己定义一个t

IOS研究之UITabBarController隐藏tabBar以及addChildViewController

 最近我所在的项目组对项目进行了一些基础组件的优化,其中有关于UITabBarController隐藏tabBar的问题感觉有必要总结下. 一,需求分析 先来说说项目基本需求:整个项目由左侧栏和主视图组成,主视图主体是一个UITabBarController,下属几个嵌套了UINavigationController的UIViewController. 要求:当在页面上下滑动的时候,根据用户手势需要隐藏显示底部栏,也就是默认的UITabBarController的tabBar. 我在设计的时

IOS开发教程--如何去除tabbar顶部线条及设置背景图片

这个问题一直比较苦恼,网上很多方法实验下来都不是很好,今天终于解决了. 直接上代码: CGRect rect = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); UIGraphicsBeginImageContext(rect.size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWit

iOS UIImageView设置为圆形

UIImageView设置为圆形的方法: _Image.layer.masksToBounds = YES; _Image.layer.cornerRadius = self.Image.frame.size.width / 2; 设置加载本地图片的方法: _Image.image = [UIImage imageNamed:@"Image"];//图片“Image”为xcassets里的set名称

iOS进入界面隐藏下方tabbar等bar

开发app时经常用到的一个基本布局框架就是tabbar+navigation,也就是下方tabbar分模块,然后在各个模块中使用导航栏深入到各个界面. 有时候我们需要在跳转到某些界面时隐藏下方的tabbar,怎么做呢,很简单: // 进入某个界面 NextViewController *nextVC = [[TypeSupplierViewController alloc] init]; // 根据点击种类不同,设立种类属性 nextVC.hidesBottomBarWhenPushed=YES

iOS去除导航栏和tabbar的1px横线

1.在自己定义的导航栏中或者设计稿中经常需要去除导航栏的1px横线,主要是颜色太不协调了 去除之前的图片 要去除这1px的横线,首先应该知道它是什么,在Xcode的界面调试中可以看到,它其实是UIImageView来的 找到横线是什么了··· 其实这是navigationBar的shadowImage,所以只要设置它为空即可,但是设置它为空之前应该先设置它的背景也为空,全部代码如下: [self.navigationController.navigationBar setBackgroundIm

iOS设置圆角及圆形图片

方方正正的样式往往会显得很生硬,而圆角的样式会让人产生别样的亲切感,现在越来越多地用到圆角,诸如用户头像之类的图片也大都用圆形来显示,本文就介绍如何设置按钮.文本框的圆角以及制作圆形的图片. 先来看看效果图: 如效果图所示,我们制作了一个圆形的头像,一个完全半圆的圆角按钮,一个小圆角的按钮,以及一个带边框且边框为圆角的label. 大概思路如下: View都有一个layer的属性,我们正是通过layer的一些设置来达到圆角的目的,因此诸如UIImageView.UIButton.UILabel等

iOS去除导航栏和tabbar的横线

导航[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; [self.navigationController.navigationBar setShadowImage:[UIImage new]]; 导航透明设置  [self.navigationController.navigationBar setTranslucent:NO