在TabBar基础上,在中间的位置加上一个Button,重新设置布局
新建一个类,继承自TabBar
OC:
#import "JSTabBar.h"
#import "Masonry.h"
@interface JSTabBar ()
@property (nonatomic,strong) UIButton *composeButton;
@end
@implementation JSTabBar
- (instancetype)init{
self = [super init];
if (self) {
//设置UI
[self setUI];
}
return self;
}
- (void)setUI{
[self addSubview:self.composeButton];
[self.composeButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.mas_equalTo(self);
}];
}
- (void)layoutSubviews{
[super layoutSubviews];
CGFloat width = [UIScreen mainScreen].bounds.size.width / 5;
CGFloat index = 0;
for (UIView *view in self.subviews) {
if ([view isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
CGRect frame = view.frame;
frame.size.width = width;
frame.origin.x = index * width;
view.frame = frame;
index ++;
if (index == 2) {
index ++;
}
}
}
}
//按钮点击事件中调用代理方法
- (void)buttonClick:(UIButton *)sender{
if ([self.tabBarDelegate respondsToSelector:@selector(tabBarDelegateWithTabBar:)]) {
[self.tabBarDelegate tabBarDelegateWithTabBar:self];
}
}
/**
* ComposeButton懒加载
*
* @return composeButton
*/
- (UIButton *)composeButton{
if (_composeButton == nil) {
_composeButton = [[UIButton alloc]init];
[_composeButton setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button"] forState:UIControlStateNormal];
[_composeButton setBackgroundImage:[UIImage imageNamed:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted];
[_composeButton setImage:[UIImage imageNamed:@"tabbar_compose_icon_add"] forState:UIControlStateNormal];
[_composeButton setImage:[UIImage imageNamed:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted];
[_composeButton sizeToFit];
[_composeButton addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
}
return _composeButton;
}
@end
自定义的TabBar样式完成,但此时还无法Push控制器,所以需要通过代理的方式,设置代理对象,进行Push操作
#import <UIKit/UIKit.h>
@class JSTabBar;
//声明协议
@protocol JSTabBarDelegate <NSObject>
@optional
//声明代理方法
- (void)tabBarDelegateWithTabBar:(JSTabBar *)tabBar;
@end
@interface JSTabBar : UITabBar
//声明代理对象
@property (nonatomic,weak) id tabBarDelegate;
@end
Swift:
// MARK - 声明协议
protocol JSTabBarDelegate : NSObjectProtocol {
func tabBarComposeButtonClick()
}
class JSTabBar: UITabBar {
//声明代理对象
weak var tabBarDelegate:JSTabBarDelegate?
private lazy var composeButton: UIButton = {
let btn = UIButton()
btn.setImage(UIImage(named: "tabbar_compose_icon_add"), forState: UIControlState.Normal)
btn.setImage(UIImage(named: "tabbar_compose_icon_add_highlighted"), forState: UIControlState.Highlighted)
btn.setBackgroundImage(UIImage(named: "tabbar_compose_button"), forState: UIControlState.Normal)
btn.setBackgroundImage(UIImage(named: "tabbar_compose_button_highlighted"), forState: UIControlState.Highlighted)
btn.sizeToFit()
return btn
}()
@objc private func composeButtonClick() -> Void {
//代理对象执行代理方法
tabBarDelegate?.tabBarComposeButtonClick()
}
// MARK: -添加button
func setupUI() -> Void {
addSubview(composeButton)
}
override init(frame: CGRect) {
super.init(frame: frame)
setupUI() //添加中间按钮
composeButton.addTarget(self, action: #selector(composeButtonClick), forControlEvents: UIControlEvents.TouchUpInside)
}
override func layoutSubviews() {
super.layoutSubviews()
//设置中间按钮的Frame
composeButton.center.x = frame.size.width * 0.5
composeButton.center.y = frame.size.height * 0.5
//调整TabBar上button的Frame NSClassFromString("UITabBarButton")
var index: CGFloat = 0
let width: CGFloat = frame.width / 5
for value in subviews {
if value.isKindOfClass(NSClassFromString("UITabBarButton")!) {
value.frame.size.width = width
value.frame.origin.x = index * width
index++
if index == 2 {
index++
}
}
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
这样自定义的TabBar就完成了,在使用上需要注意:
因为UITabBarController的tabBar为只读属性,所以无法按照正常方式设置,这里就需要通过KVC设置只读属性
在ViewDidLoad中
OC:
JSTabBar *tabBar = [[JSTabBar alloc]init];
tabBar.tabBarDelegate = self;
[self setValue:tabBar forKey:@"tabBar"];
Swift:
let tabBar = JSTabBar()
tabBar.tabBarDelegate = self
setValue(tabBar, forKey: "tabBar")
补充:
1.在OC中不能像Swift那样直接设置frame属性,需要借助中间变量
2.tabBar为只读属性,需要借助KVC设置
3.自定义布局完成后,还需要通过代理或者Block/闭包的方式委托控制器实现Push操作
4.Swift下重写了init(frame: CGRect)方法,就不再支持xib和StoryBoard的方式,如果需要用到xib或storyBoard,需要自定义方法来创建TabBar