在TabBar基礎(chǔ)上,在中間的位置加上一個Button,重新設(shè)置布局
custom_tabBar.png
新建一個類,繼承自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) {
//設(shè)置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 ++;
}
}
}
}
//按鈕點擊事件中調(diào)用代理方法
- (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控制器,所以需要通過代理的方式,設(shè)置代理對象,進行Push操作
#import <UIKit/UIKit.h>
@class JSTabBar;
//聲明協(xié)議
@protocol JSTabBarDelegate <NSObject>
@optional
//聲明代理方法
- (void)tabBarDelegateWithTabBar:(JSTabBar *)tabBar;
@end
@interface JSTabBar : UITabBar
//聲明代理對象
@property (nonatomic,weak) id tabBarDelegate;
@end
Swift:
// MARK - 聲明協(xié)議
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 {
//代理對象執(zhí)行代理方法
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()
//設(shè)置中間按鈕的Frame
composeButton.center.x = frame.size.width * 0.5
composeButton.center.y = frame.size.height * 0.5
//調(diào)整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為只讀屬性,所以無法按照正常方式設(shè)置,這里就需要通過KVC設(shè)置只讀屬性
在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那樣直接設(shè)置frame屬性,需要借助中間變量
2.tabBar為只讀屬性,需要借助KVC設(shè)置
3.自定義布局完成后,還需要通過代理或者Block/閉包的方式委托控制器實現(xiàn)Push操作
4.Swift下重寫了init(frame: CGRect)方法,就不再支持xib和StoryBoard的方式,如果需要用到xib或storyBoard,需要自定義方法來創(chuàng)建TabBar