UINavigation導航欄和UITabbar佈局和樣式

自定義UITabBarController

 

能夠在ViewDidLoad裏設置子控制器。固然其餘地方也是能夠的,可是放在這裏能夠更加有條理。數組

 

初始化

 

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 添加全部的子控制器
    [self addAllChildVcs];
    
    // 建立自定義tabbar
    [self addCustomTabBar];
}

 

設置導航和tab標題

 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];

 

 

 

自定義UITabbar

 

自定義一個TabBar繼承自UITabBar,而後在layoutSubviews裏面設置子控件的frameapp

 

初始化設置能夠放在initWithFrame中進行ide

 

 

設置選中tabBarItem 的tab bar上渲染的顏色(此圖片獎顯示在TabBarItem後面)

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];

 

 

自定義UINavigationController

設置主題

/**
 *  當第一次使用這個類的時候調用1次
 */
+ (void)initialize
{
    // 設置UINavigationBarTheme的主
    [self setupNavigationBarTheme];
    
    // 設置UIBarButtonItem的主題
    [self setupBarButtonItemTheme];
}

 

經過設置+ (instancetype)appearance;作統一的設置.net

設置UINavigationBar的主題

/**
 *  設置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的主題

/**
 *  設置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的樣式只要從新自定義其屬性就能夠代理

 

統一處理全部和導航有關的push事件

在自定義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];
}

 

 

 

一種調整Tabbar外觀的思路

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

相關文章
相關標籤/搜索