iOS中定制tabBar,目前無非就兩種方式:
第一種是繼承系統的UITabBar,在子類里進行自定義修改,實例化之后利用KVC setTabBar: 即可
第二種是自定義View,創建若干個需要的按鈕,按鈕的點擊事件去Hook系統的TabBar Item的點擊事件,主要是系統的TabBarController的一個屬性,即selectedIndex 起到切換子控制器的作用,也就是說按鈕的選中事件和切換子控制器是一致的,利用下標去映射就ok啦
首先拿到問題,進行如下分析:
- 1 自定義需要什么東西 ?
- 2 需要實現什么樣的功能?
- 3 代碼如何封裝,可復用性和穩定性更高?
- 4 用什么方式實現的更優雅,更簡單可控
......
#1. 自定義需要準備好圖片(選中與常態下的兩套圖標)
#2. 有特殊需求的時候才需要特別定制,一般情況下監聽點擊事情,模仿系
#統切換子控制器的動作即可
#3. 一般會做成公共的API調用接口,如果是在系統的基礎上修改,
#使用代理無疑是更優雅的選擇,直接使用系統的代理, 如果是自定義的
#話,block和代理均可,個人比較傾向于使用代理
#4. 如果是繼承系統的UITabBar的基礎上進行修改的話,建議用純代碼,
#因為這樣修改起來比較方便, 對于自定義View的方式來定制的話,如果是
#簡單的監聽點擊或者不是什么復雜UI,我倒是覺得XIB也無傷大雅,怎么
#簡單怎么來,除非是情況比較復雜,那就只得純代碼來懟.
廢話不多說,進入正題,這里對于系統的UITabBar簡單定制不再作過多獒述,網上太多類似教程, 基本上是開箱即用
XIB定制 ----自定義View實現TabBar功能
拽UI
根據自己業務和UI進行拖拽
拉約束
只可意會,不可描述,拉得多了自然就會了
添加監聽事件
直接拖線就好辣,還講個鬼哦
處理點擊邏輯
判斷選中與未選中兩種狀態下的顯示邏輯
打通UITabBarController
selectedIndex
與 按鈕選中下標是一致的就ok??
文筆不好,老老實實做筆記,貼代碼大法
<!--- TabBar --->
@protocol WGBTabBarDelegate <NSObject>
- (void)selectedClickWithIndex:(NSInteger)index;
@end
@interface WGBTabBar : UIView
@property (nonatomic,weak) id<WGBTabBarDelegate> wgbDelegate;
@end
#import "WGBTabBar.h"
@interface WGBTabBar ()
@property (nonatomic,strong) UIButton *tempButton;
@property (weak, nonatomic) IBOutlet UIButton *oneButton;
@end
@implementation WGBTabBar
- (void)awakeFromNib{
[super awakeFromNib];
self.tempButton = self.oneButton;
}
/// 0,1,2,3
- (IBAction)tabbarClickAction:(UIButton *)sender {
sender.backgroundColor = [UIColor blueColor];
self.tempButton.backgroundColor = [UIColor purpleColor];
self.tempButton.selected = NO;
self.tempButton = sender;
if ([self.wgbDelegate respondsToSelector: @selector(selectedClickWithIndex:)]) {
[self.wgbDelegate selectedClickWithIndex: sender.tag];
}
}
@end
<!--- TabBarViewController --->
#import "WGBTabBarViewController.h"
#import "WGBTabBar.h"
#import "OneViewController.h"
#import "TwoViewController.h"
#import "ThreeViewController.h"
#import "FourViewController.h"
@interface WGBTabBarViewController ()<WGBTabBarDelegate>
@end
@implementation WGBTabBarViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self createTabBar];
[self initViewContreollers];
}
- (void)createTabBar{
CGFloat kWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat kHeight = [UIScreen mainScreen].bounds.size.height;
CGFloat kTabBarHeight = 49;
WGBTabBar *tabBar = [[NSBundle mainBundle] loadNibNamed:@"WGBTabBar" owner:nil options:0][0];
tabBar.wgbDelegate = self;
tabBar.frame = CGRectMake(0, kHeight - kTabBarHeight, kWidth , kTabBarHeight);
self.tabBar.hidden = YES; ///這句代碼很關鍵 ,之前沒隱藏,總感覺有什么東西擋住
[self.view addSubview: tabBar] ;
}
#pragma mark- <WGBTabBarDelegate>
- (void)selectedClickWithIndex:(NSInteger)index{
self.selectedIndex = index;
}
- (void)initViewContreollers{
OneViewController *oneVC = [[OneViewController alloc] init];
TwoViewController *twoVC = [[TwoViewController alloc] init];
ThreeViewController *threeVC = [[ThreeViewController alloc] init];
FourViewController *fourVC = [[FourViewController alloc] init];
NSArray *VCs = @[oneVC,twoVC,threeVC,fourVC];
NSMutableArray *childsVC = [NSMutableArray array];
for (UIViewController *VC in VCs) {
UINavigationController *rootVC = [[UINavigationController alloc] initWithRootViewController:VC];
VC.title = NSStringFromClass([VC class]);
[childsVC addObject: rootVC];
}
self.viewControllers = childsVC;
}
@end
(Tips)注意:
系統的tabBar一定要隱藏掉,不然會干擾點擊事件,讓你產生錯覺,內部實現不隱藏的話應該是會放到最上層
做了一個最簡單的,沒有添加圖片,純文字表達一下意思咯,意思意思咯
Simulator Screen Shot 2017年7月3日 00.33.04.png
2017 年 07 月 12日 更新一個新姿勢
如何優雅的隱藏tabBar?
除了將自定義tabBar的hidden
屬性提出來,似乎并沒有什么太好的方案. 而hook系統的"hidesBottomBarWhenPushed"屬性,這個需要繼承系統的UITabBar定制的才適用.
下面簡述一下我的做法
#1. 將自定義view(即tabBar) 的hidden屬性提取出來,可以通過Appdelegate 做成全局的屬性
#2. 在基類里定義一個屬性,hideTabBar,用于獲取子類設置的顯示或者隱藏的狀態進行操作
#3. 在最外層,也就是TabBarController包裹的子VC里的
#`- (void)viewWillAppear:(BOOL)animated`
# `- (void)viewWillDisappear:(BOOL)animated`
#這兩個方法里設置顯示或者隱藏
#4. 在點擊TabBar那個監聽方法里,設置自定義TabBar一直顯示,不然會出現切換TabBarController子控制器的也會出現忽閃忽閃的感覺...
貼代碼大法:
step 1
#import <UIKit/UIKit.h>
#import "WGBTabBar.h"
@interface WGBTabBarViewController : UITabBarController
@property (nonatomic,strong) WGBTabBar *wgbTabBar;
@end
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (nonatomic,strong) WGBTabBarViewController *tabBarController ;
@end
step 2
- (void)setHiddenTabBar:(BOOL)hiddenTabBar{
_hiddenTabBar = hiddenTabBar;
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
appDelegate.tabBarController.wgbTabBar.hidden = hiddenTabBar;
}
step 3
在首頁那個層級的VC里如下方法設置:
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
self.hiddenTabBar = NO;
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
self.hiddenTabBar = YES;
}
step 4
#pragma mark- <WGBTabBarDelegate>
- (void)selectedClickWithIndex:(NSInteger)index{
self.selectedIndex = index;
self.wgbTabBar.hidden = NO;
}