如图 实现上图这样 自己定义的tabbar 。当然方法有多种,比如自定义一个view的大小等于tabbar的大小,然后对View进行操作。如果使用OC的话这里可以用KVC来替换系统的tabBar。如果是Swift,不用KVC就可以完成了
下面先聊聊OC的,一共可以概括为3步
1.因为直接用代码怼上的,这里先设置下window.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = [[CYWBaseTabbarController alloc] init];
[self.window makeKeyAndVisible];
return YES;
}
2.自定义一个UITabBar,重写init方法,然后在layoutSubviews方法中对子控件的frame进行修改。
#import "CYWBaseTabBar.h"
@interface CYWBaseTabBar ()
/**
撰写按钮
*/
@property (nonatomic,strong)UIButton *centerBtn;
@end
@implementation CYWBaseTabBar
-(instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
[self addSubview:self.centerBtn];
}
return self;
}
///MARK:实际开中需要代理传点击事件
-(void)centerBtnClick{
NSLog(@"撰写按钮");
}
-(void)layoutSubviews{
[super layoutSubviews];
///设置centerBtn的frame
CGPoint p = self.centerBtn.center;
p.x = self.frame.size.width / 2;
p.y = self.frame.size.height / 2;
self.centerBtn.center = p;
///获取宽
CGFloat subW = self.frame.size.width / 5;
NSInteger i = 0;
for (UIView *view in self.subviews) {
/// 判断子控件是否是UITabBarButton
if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
CGRect temp = view.frame;
temp.size.width = subW;
temp.origin.x = subW * i;
view.frame = temp;
i++;
if (i == 2) {///当为2的时候,第三个子控件就是centerBtn 需要加1
i ++;
}
}
}
}
///MARK:懒加载
-(UIButton *)centerBtn{
if (_centerBtn == nil) {
_centerBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[_centerBtn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
[_centerBtn setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
[_centerBtn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
[_centerBtn setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
[_centerBtn addTarget:self action:@selector(centerBtnClick) forControlEvents:UIControlEventTouchUpInside];
[_centerBtn sizeToFit];
}
return _centerBtn;
}
@end
3.自定义一个UITabBarController,在viewDidLoad中初始化子控制器。也同样在ViewDidLoad中用KVC替换系统的tarBar,值得注意的是tabBar不要打错了,那样KVC会崩掉
#import "CYWBaseTabbarController.h"
#import "CYWBaseViewController.h"
#import "CYWBaseTabBar.h"
@interface CYWBaseTabbarController ()
@end
@implementation CYWBaseTabbarController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setupTabbar];
[self addCenterButton];
self.selectedIndex = 1;
}
-(void)addCenterButton{
CYWBaseTabBar *tabbar = [[CYWBaseTabBar alloc] init];
///KVC 修改系统tabBar
[self setValue:tabbar forKey:@"tabBar"];
}
/**
设置tabBar
*/
-(void)setupTabbar{
/// MARK:实际情况中 arr可以从服务器获取 从而动态的修改图片和名字
NSArray *arr = @[@{@"title":@"首页",@"image":@"home",@"cls":@"CYWHomeViewController"},
@{@"title":@"消息",@"image":@"message_center",@"cls":@"CYWMessageViewController"},
@{@"title":@"发现",@"image":@"discover",@"cls":@"CYWDiscoveryViewController"},
@{@"title":@"我的",@"image":@"profile",@"cls":@"CYWProfileViewController"}
];
NSMutableArray *controllerArrM = [NSMutableArray arrayWithCapacity:arr.count];
for (NSDictionary *dict in arr) {
[controllerArrM addObject:[self contrllers:dict]];
}
self.viewControllers = controllerArrM;
}
/**
给个字典 返回一个控制器
@param dict 传入创建控制器的字典
@return 返回的控制器
*/
-(UIViewController *)contrllers:(NSDictionary *)dict{
NSString *title = dict[@"title"];
NSString *imageName = dict[@"image"];
NSString *clsName = dict[@"cls"];
/// 基类控制器
CYWBaseViewController *baseVC = [(CYWBaseViewController *) [NSClassFromString(clsName) alloc] init];
baseVC.title = title;
[baseVC.tabBarItem setImage:[[UIImage imageNamed:[NSString stringWithFormat:@"tabbar_%@",imageName]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
[baseVC.tabBarItem setSelectedImage:[[UIImage imageNamed:[NSString stringWithFormat:@"tabbar_%@_selected",imageName]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
[baseVC.tabBarItem setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor orangeColor]} forState:UIControlStateSelected];
return baseVC;
}
@end
接下来是Swift的,共2步
1.第1步与OC相同,初始化window
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// sleep(2)
window = UIWindow()
window?.rootViewController = CYWMianController()
window?.makeKeyAndVisible()
return true
}
2.这里就不需要用到自定义tabBar了,也就用不到KVC了。因为在Swfit中tabBar.bounds中多了一个方法:要插入的位置 x y分别代表水平、垂直方向(不知道OC有没有同样的方法)
@available(iOS 2.0, *)
public func insetBy(dx: CGFloat, dy: CGFloat) -> CGRect
下面就直接粘代码了
import UIKit
class CYWMianController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
setupTabBar()
addCenterBtn()
}
//MARK:懒加载撰写按钮
private lazy var centerBtn:UIButton = {
let btn = UIButton()
btn.setImage(UIImage(named:"tabbar_compose_icon_add"), for: UIControlState(rawValue: 0))
btn.setImage(UIImage(named:"tabbar_compose_icon_add_highlighted "), for: UIControlState(rawValue: 1))
btn.setBackgroundImage(UIImage(named:"tabbar_compose_button"), for: UIControlState(rawValue: 0))
btn.addTarget(self, action:#selector(centerBtnClick), for: .touchUpInside)
return btn
}()
//MARK:添加撰写按钮
private func addCenterBtn (){
tabBar.addSubview(centerBtn)
let count = CGFloat(childViewControllers.count)
let w = tabBar.bounds.width / count - 1
centerBtn.frame = tabBar.bounds.insetBy(dx: 2 * w, dy: 0)
}
//MARK:撰写按钮点击事件
@objc private func centerBtnClick(){
print("撰写微博")
}
//MARK:添加tabbleBar
private func setupTabBar() -> () {
let arr = [
["title":"主页","cls":"CYWHomeViewController","imageName":"home",
"vistorInfo":["imageName":"",
"message":"就是爱你爱你,就是爱你爱你,就是爱你爱你,就是爱你爱你"]],
["title":"消息","cls":"CYWMessageViewController","imageName":"message_center",
"vistorInfo":["imageName":"visitordiscover_image_message",
"message":"就是爱你爱你,就是爱你爱你,就是爱你爱你,就是爱你爱你"]],
["cls":"UIViewController"],
["title":"发现","cls":"CYWDiscoveyViewController","imageName":"discover",
"vistorInfo":["imageName":"visitordiscover_image_message",
"message":"就是爱你爱你,就是爱你爱你,就是爱你爱你,就是爱你爱你"]],
["title":"我","cls":"CYWProfileViewController","imageName":"profile",
"vistorInfo":["imageName":"visitordiscover_image_profile",
"message":"哇真的恐怖,哇真的恐怖,哇真的恐怖哇真的恐怖哇真的恐怖"]],
]
var arrM = [UIViewController]()
for dict in arr {
let vc = controllers(dict: dict as [String : AnyObject])
arrM.append(vc)
}
viewControllers = arrM
}
private func controllers(dict : [String:AnyObject]) -> UIViewController {
guard let title = dict["title"] as? String,
let imageName = dict["imageName"] as? String,
let clsName = dict["cls"] as? String,
let cls = NSClassFromString(Bundle.main.namespace() + "." + clsName) as? CYWBaseViewController.Type,
let vistorDict = dict["vistorInfo"] as? [String:String]
else {
return UIViewController()
}
let vc = cls.init()
vc.title = title
vc.tabBarItem.image = UIImage(named: "tabbar_" + imageName)?.withRenderingMode(.alwaysOriginal)
vc.tabBarItem.selectedImage = UIImage(named: "tabbar_" + imageName + "_selected")?.withRenderingMode(.alwaysOriginal)
vc.tabBarItem.setTitleTextAttributes([NSForegroundColorAttributeName : UIColor.orange], for:UIControlState(rawValue: 1))
vc.infoDictionary = vistorDict
return CYWNavigationController(rootViewController: vc)
}
}