能夠在ViewDidLoad裏設置子控制器。固然其餘地方也是能夠的,可是放在這裏能夠更加有條理。數組
- (void)viewDidLoad { [super viewDidLoad]; // 添加全部的子控制器 [self addAllChildVcs]; // 建立自定義tabbar [self addCustomTabBar]; }
childVc.tabBarItem.title = title; // tabbar標籤上標籤 childVc.navigationItem.title = title; // 導航欄上標籤
childVc.tabBarItem.image = [UIImage imageWithName:imageName]; // 聲明這張圖片用原圖(不要渲染) selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; childVc.tabBarItem.selectedImage = selectedImage;
// 設置tabBarItem的普通文字顏色 NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; textAttrs[UITextAttributeTextColor] = [UIColor blackColor]; textAttrs[UITextAttributeFont] = [UIFont systemFontOfSize:10]; [childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal]; // 設置tabBarItem的選中文字顏色 NSMutableDictionary *selectedTextAttrs = [NSMutableDictionary dictionary]; selectedTextAttrs[UITextAttributeTextColor] = [UIColor orangeColor]; [childVc.tabBarItem setTitleTextAttributes:selectedTextAttrs forState:UIControlStateSelected];
自定義一個TabBar繼承自UITabBar,而後在layoutSubviews裏面設置子控件的frameapp
初始化設置能夠放在initWithFrame中進行ide
self.selectionIndicatorImage = [UIImage imageWithName:@"navigationbar_back_highlighted"];
self.backgroundImage = [UIImage imageWithName:@"tabbar_background"]
須要自定義佈局tabbar時,能夠改寫佈局
/** * 佈局子控件 */ - (void)layoutSubviews { }
上面的UITabBar是自定義的,加上了一個UIButton字體
#import "HMTabBar.h" @interface HMTabBar() @property (nonatomic, weak) UIButton *plusButton; @end @implementation HMTabBar - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { if (!iOS7) { self.backgroundImage = [UIImage imageWithName:@"tabbar_background"]; } self.selectionIndicatorImage = [UIImage imageWithName:@"navigationbar_button_background"]; // 添加加號按鈕 [self setupPlusButton]; } return self; } /** * 添加加號按鈕 */ - (void)setupPlusButton { UIButton *plusButton = [[UIButton alloc] init]; // 設置背景 [plusButton setBackgroundImage:[UIImage imageWithName:@"tabbar_compose_button"] forState:UIControlStateNormal]; [plusButton setBackgroundImage:[UIImage imageWithName:@"tabbar_compose_button_highlighted"] forState:UIControlStateHighlighted]; // 設置圖標 [plusButton setImage:[UIImage imageWithName:@"tabbar_compose_icon_add"] forState:UIControlStateNormal]; [plusButton setImage:[UIImage imageWithName:@"tabbar_compose_icon_add_highlighted"] forState:UIControlStateHighlighted]; [plusButton addTarget:self action:@selector(plusClick) forControlEvents:UIControlEventTouchUpInside]; // 添加 [self addSubview:plusButton]; self.plusButton = plusButton; } - (void)plusClick { HMLog(@"plusClick----"); // 通知代理 if ([self.delegate respondsToSelector:@selector(tabBarDidClickedPlusButton:)]) { [self.delegate tabBarDidClickedPlusButton:self]; } } /** * 佈局子控件 */ - (void)layoutSubviews { [super layoutSubviews]; // 設置plusButton的frame [self setupPlusButtonFrame]; // 設置全部tabbarButton的frame [self setupAllTabBarButtonsFrame]; } /** * 設置全部plusButton的frame */ - (void)setupPlusButtonFrame { self.plusButton.size = self.plusButton.currentBackgroundImage.size; self.plusButton.center = CGPointMake(self.width * 0.5, self.height * 0.5); } /** * 設置全部tabbarButton的frame */ - (void)setupAllTabBarButtonsFrame { int index = 0; // 遍歷全部的button for (UIView *tabBarButton in self.subviews) { // 若是不是UITabBarButton, 直接跳過 if (![tabBarButton isKindOfClass:NSClassFromString(@"UITabBarButton")]) continue; // 根據索引調整位置 [self setupTabBarButtonFrame:tabBarButton atIndex:index]; // 索引增長 index++; } } /** * 設置某個按鈕的frame * * @param tabBarButton 須要設置的按鈕 * @param index 按鈕所在的索引 */ - (void)setupTabBarButtonFrame:(UIView *)tabBarButton atIndex:(int)index { // 計算button的尺寸 CGFloat buttonW = self.width / (self.items.count + 1); CGFloat buttonH = self.height; tabBarButton.width = buttonW; tabBarButton.height = buttonH; if (index >= 2) { tabBarButton.x = buttonW * (index + 1); } else { tabBarButton.x = buttonW * index; } tabBarButton.y = 0; } @end
設置TabBarItematom
/** * 添加一個子控制器 * * @param childVc 子控制器對象 * @param title 標題 * @param imageName 圖標 * @param selectedImageName 選中的圖標 */ - (void)addOneChlildVc:(UIViewController *)childVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName { // 設置標題 childVc.title = title; // 設置圖標 childVc.tabBarItem.image = [UIImage imageWithName:imageName]; // 設置tabBarItem的普通文字顏色 NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; textAttrs[UITextAttributeTextColor] = [UIColor blackColor]; textAttrs[UITextAttributeFont] = [UIFont systemFontOfSize:10]; [childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal]; // 設置tabBarItem的選中文字顏色 NSMutableDictionary *selectedTextAttrs = [NSMutableDictionary dictionary]; selectedTextAttrs[UITextAttributeTextColor] = [UIColor orangeColor]; [childVc.tabBarItem setTitleTextAttributes:selectedTextAttrs forState:UIControlStateSelected]; // 設置選中的圖標 UIImage *selectedImage = [UIImage imageWithName:selectedImageName]; if (iOS7) { // 聲明這張圖片用原圖(別渲染) selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; } childVc.tabBarItem.selectedImage = selectedImage; // 添加爲tabbar控制器的子控制器 HMNavigationController *nav = [[HMNavigationController alloc] initWithRootViewController:childVc]; [self addChildViewController:nav]; }
須要從新調整子控件的佈局時,調用setNeedsLayout方法,此方法會自動調用setFrame方法spa
[self.tabBar setNeedsLayout];
/** * 當第一次使用這個類的時候調用1次 */ + (void)initialize { // 設置UINavigationBarTheme的主 [self setupNavigationBarTheme]; // 設置UIBarButtonItem的主題 [self setupBarButtonItemTheme]; }
經過設置+ (instancetype)appearance;作統一的設置.net
/** * 設置UINavigationBarTheme的主題 */ + (void)setupNavigationBarTheme { UINavigationBar *appearance = [UINavigationBar appearance]; // 設置導航欄背景 if (!iOS7) { [appearance setBackgroundImage:[UIImage imageWithName:@"navigationbar_background"] forBarMetrics:UIBarMetricsDefault]; } // 設置文字屬性 NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; textAttrs[UITextAttributeTextColor] = [UIColor blackColor]; textAttrs[UITextAttributeFont] = [UIFont boldSystemFontOfSize:20]; // UIOffsetZero是結構體, 只要包裝成NSValue對象, 才能放進字典\數組中,去除陰影效果 textAttrs[UITextAttributeTextShadowOffset] = [NSValue valueWithUIOffset:UIOffsetZero]; [appearance setTitleTextAttributes:textAttrs]; }
/** * 設置UIBarButtonItem的主題 */ + (void)setupBarButtonItemTheme { // 經過appearance對象能修改整個項目中全部UIBarButtonItem的樣式 UIBarButtonItem *appearance = [UIBarButtonItem appearance]; /**設置文字屬性**/ // 設置普通狀態的文字屬性 NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary]; textAttrs[UITextAttributeTextColor] = [UIColor orangeColor]; textAttrs[UITextAttributeFont] = [UIFont systemFontOfSize:15]; textAttrs[UITextAttributeTextShadowOffset] = [NSValue valueWithUIOffset:UIOffsetZero]; [appearance setTitleTextAttributes:textAttrs forState:UIControlStateNormal]; // 設置高亮狀態的文字屬性 NSMutableDictionary *highTextAttrs = [NSMutableDictionary dictionaryWithDictionary:textAttrs]; highTextAttrs[UITextAttributeTextColor] = [UIColor redColor]; [appearance setTitleTextAttributes:highTextAttrs forState:UIControlStateHighlighted]; // 設置不可用狀態(disable)的文字屬性 NSMutableDictionary *disableTextAttrs = [NSMutableDictionary dictionaryWithDictionary:textAttrs]; disableTextAttrs[UITextAttributeTextColor] = [UIColor lightGrayColor]; [appearance setTitleTextAttributes:disableTextAttrs forState:UIControlStateDisabled]; /**設置背景**/ // 技巧: 爲了讓某個按鈕的背景消失, 能夠設置一張徹底透明的背景圖片 [appearance setBackgroundImage:[UIImage imageWithName:@"navigationbar_button_background"] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault]; }
若是須要更改後續UIBarButtonItem的樣式只要從新自定義其屬性就能夠代理
在自定義UINavigationController中重寫-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animate;方法code
/** * 能攔截全部push進來的子控制器 */ - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { if (self.viewControllers.count > 0) { // 若是如今push的不是棧底控制器(最早push進來的那個控制器) viewController.hidesBottomBarWhenPushed = YES; // 設置導航欄按鈕 viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithImageName:@"navigationbar_back" highImageName:@"navigationbar_back_highlighted" target:self action:@selector(back)]; viewController.navigationItem.rightBarButtonItem = [UIBarButtonItem itemWithImageName:@"navigationbar_more" highImageName:@"navigationbar_more_highlighted" target:self action:@selector(more)]; } [super pushViewController:viewController animated:animated]; }
UITabBar的樣式和預期的不一樣,首先在viewDidLoad方法中輸出self.view.subViews
-(void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; NSLog(@"%@",self.tabBar.subViews); }
輸出結果
(
"<_UITabBarBackgroundView: 0x7fc021df6590; frame = (0 0; 375 49); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fc02400a060>>",
"<UITabBarButton: 0x7fc021ddcaa0; frame = (2 1; 90 48); opaque = NO; layer = <CALayer: 0x7fc021e084e0>>",
"<UITabBarButton: 0x7fc021de4230; frame = (96 1; 90 48); opaque = NO; layer = <CALayer: 0x7fc021de4b40>>",
"<UITabBarButton: 0x7fc021deb780; frame = (190 1; 89 48); opaque = NO; layer = <CALayer: 0x7fc021e06340>>",
"<UITabBarButton: 0x7fc021e0ef50; frame = (283 1; 90 48); opaque = NO; layer = <CALayer: 0x7fc021de5f90>>",
"<UIImageView: 0x7fc02400b8f0; frame = (0 -0.5; 375 0.5); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fc02400b520>>"
)
可是UITabBarButton並非公開的,因此查看其父類,是UIControl
繼續遍歷其subview,找到一個select有關的view將其從super中移除。能夠用這個方法作必定的遍歷,調整特定屬性
-(void)viewDidAppear:(BOOL)animated{ [super viewDidAppear:animated]; for (UIView *child in self.tabBar.subviews) { NSLog(@"%@",child.superclass); NSLog(@"%@",child.subviews); for (UIView * childchild in child.subviews) { if([childchild isKindOfClass:[UILabel class]]){ UILabel *label=(UILabel *)childchild; label.font=[UIFont systemFontOfSize:15]; } } } NSLog(@"%@",self.tabBar.subviews); }
runtime機制
KVC修改readonly的屬性
[self setValue:customTabBar forKeyPath:@"tabBar"];
NSLog(@"%p",customTabBar);
在系統的導航控制器基類中設置
UIGestureRecognizerDelegate 聲明代理
self.interactivePopGestureRecognizer.delegate = self;
// 做用:攔截手勢觸發 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ // 注意:只有非根控制器纔有滑動返回功能,根控制器沒有。 // 判斷導航控制器是否只有一個子控制器,若是隻有一個子控制器,確定是根控制器 if(self.viewControllers.count == 1){ // 表示用戶在根控制器界面,就不須要觸發滑動手勢, return NO; } return YES; }
參考資料
http://blog.csdn.net/u011452278/article/details/51535506