IOS實現中間凸起圓形TabBar

  中間凸起的圓形TabBar曾經比較流行,相似於閒魚之類的APP就使用了中間凸起TabBar,這兩天本身動手實現了一個,效果圖以下:app

  大體原理:重寫UITabBar和UITabBarController,在UITabBar中枚舉全部的UITabBarButton類型子控件,從新設置子控件的位置,爲中間的圓形按鈕預留位置,在layoutsubviews中添加圓形按鈕而且重寫hitTest方法,判斷觸摸是否位於圓形按鈕區域,若是是,則經過圓形按鈕響應點擊事件。在UITabBarController咱們須要用咱們本身建立的UITabBar去替換系統原來的UITabBar,在建立UITabBarController的時候也須要用咱們本身建立的UITabBarController。ide

  代碼以下:ui

  MyUITabBar.mthis

#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.hatom

#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.mspa

#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.net

#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.mrest

#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

   部分頭文件和TabViewController一、TabViewController2的文件沒有放上來,由於這裏面沒有添加任何本身的代碼。源碼下載連接:http://download.csdn.net/detail/lzm2625347497/9571511code

相關文章
相關標籤/搜索