改造 UITabBarController

之前看到网上有不少同学自己实现了一些别具一格的系统控件,有一些做得很漂亮。今天我看到了一个UITabBarController的自定义实现,于是我也自己实现了一个TabBarController; 与其他自定义的实现不同,我这个实现自己不新增任何类,也不添加任何资源文件(如图片),完全靠改造系统的UITabBarController实现,在这里我自定义了一个继承UITabBarController的类RZTabBarController(其实也可以不定义它,但是处于个人的私心,我还是用我的名字前缀命名他吧……^_^……)。好,闲话少叙,贴出我的实现代码:

//
//  RZTabBarController.h
//  CustomTabBarController
//
#import <UIKit/UIKit.h>

@interface RZTabBarController : UITabBarController <UITabBarControllerDelegate> {
@private
    NSUInteger lastSelectedIndex;
}

@end

在这个实现文件中我为了不让它感觉太空旷就加了一个私有变量 lastSelectedIndex 我们将在实现文件中用到它,动然如果我们不自定义一个新的类,我们完全可以将它作为一个全局静态变量声明在实现文件中。

//
//  RZTabBarController.m
//  CustomTabBarController
//

#import "RZTabBarController.h"
#import <QuartzCore/QuartzCore.h>

@implementation RZTabBarController
// The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization.
        self.delegate = self;
    }
    return self;
}


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
    self.delegate = self;
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc. that aren't in use.
}

- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (void)dealloc {
    [super dealloc];
}

#pragma mark -
#pragma mark UITabBarControllerDelegate
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
    NSInteger index = tabBarController.selectedIndex;
    if (index > 4) {
        index = 4;
    }
    UIControl *selectedItem = [[tabBarController.tabBar subviews] objectAtIndex:index];
    UIView *indicatorView = [selectedItem valueForKey:@"_selectedIndicator"];
    NSInteger distanceIndex = lastSelectedIndex - index;
    CGRect originFrame = indicatorView.frame;
    CGRect customFrame = indicatorView.frame;
    customFrame.origin.x = distanceIndex * customFrame.size.width;
    indicatorView.frame = customFrame;
    [UIView beginAnimations:nil context:UIGraphicsGetCurrentContext()];
    [UIView setAnimationDuration:0.25];
    indicatorView.frame = originFrame;
    [UIView commitAnimations];
    
    CATransition *animation = [CATransition animation];
    animation.timingFunction = UIViewAnimationCurveEaseInOut;
    animation.subtype = kCATransitionFromBottom;
    animation.duration = 0.25;
    
    UIImageView *imageView = nil;
    NSArray *subviews = [selectedItem subviews];
    if ([subviews count] > 2) {
        imageView = [subviews objectAtIndex:1];
    } else {
        imageView = [subviews objectAtIndex:0];
    }
    animation.type = @"rippleEffect";
    [imageView.layer addAnimation:animation forKey:@"anmation"];
    
    UILabel *label = [selectedItem valueForKey:@"_label"];
    animation.type = @"cube";
    [label.layer addAnimation:animation forKey:@"anmation"];
    
    lastSelectedIndex = index;
}

- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed {
    NSArray *array = tabBarController.tabBar.subviews;
    array = [array sortedArrayUsingComparator:^(id control1, id control2) {
        NSComparisonResult result = NSOrderedSame;
        if (((UIControl *)control1).frame.origin.x > ((UIControl *)control2).frame.origin.x) {
            result = NSOrderedDescending;
        } else if (((UIControl *)control1).frame.origin.x == ((UIControl *)control2).frame.origin.x) {
            result = NSOrderedSame;
        } else if (((UIControl *)control1).frame.origin.x < ((UIControl *)control2).frame.origin.x) {
            result = NSOrderedAscending;
        }
        return result;
    }];
    [tabBarController.tabBar setValue:array forKey:@"_subviewCache"];
}

@end

其实在实现文件中我也只是对UITabBarController的点代理方法进行了个实现,代码如是很多相信大家看到后就自然明白了,可能唯一比较高级的一点就是用到了KeyValueCoding编程,但是使用这个东西的使用我已经在前面的随笔中也已经讲道了,这里是相同的作用。

因为这个一个动态的过程,我就没有办法给大家贴出图来了,想要试试的同学可以将我的代码粘贴一下。

原文地址:https://www.cnblogs.com/OtionSky/p/iOS_TabBar_Customize.html