三:新浪微博--主框架的搭建

一:主框架分析:ios

1:主框架的效果圖以下:底部有一個tabBar,點擊tabBar按鈕切換首頁,信息,發現 和我幾個界面。則考慮將UITabBarController做爲窗口的根視圖控制器,因此新建類繼承UITabBarController,用來封裝主框架數組

app

2:封裝根視圖控制器UITabBarController的代碼:框架

  1 #import "HMTabBarViewController.h"
  2 #import "HMHomeViewController.h"
  3 #import "HMMessageViewController.h"
  4 #import "HMDiscoverViewController.h"
  5 #import "HMProfileViewController.h"
  6 #import "HMNavigationController.h"
  7 #import "HMTabBar.h"
  8 #import "HMComposeViewController.h"
  9 #import "HMUserTool.h"
 10 #import "HMAccount.h"
 11 #import "HMAccountTool.h"
 12 
 13 @interface HMTabBarViewController () <HMTabBarDelegate, UITabBarControllerDelegate>
 14 @property (nonatomic, weak) HMHomeViewController *home;
 15 @property (nonatomic, weak) HMMessageViewController *message;
 16 @property (nonatomic, weak) HMProfileViewController *profile;
 17 @property (nonatomic, weak) UIViewController *lastSelectedViewContoller;
 18 @end
 19 
 20 @implementation HMTabBarViewController
 21 - (void)viewDidLoad
 22 {
 23     [super viewDidLoad];
 24     
 25     //1:本身設爲本身的代理,爲了監聽自身的改變
 26      self.delegate = self;
 27     
 28     //2:添加全部的子控制器
 29     [self addAllChildVcs];
 30     
 31     //3:建立自定義tabbar
 32     [self addCustomTabBar];
 33     
 34     //4:利用定時器得到用戶的未讀數
 35 //    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(getUnreadCount) userInfo:nil repeats:YES];
 36 //    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
 37 }
 38 
 39 #pragma mark -- 當切換控制器時,監聽自身切換控制器
 40 
 41 - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UINavigationController *)viewController
 42 {
 43     UIViewController *vc = [viewController.viewControllers firstObject];
 44     if ([vc isKindOfClass:[HMHomeViewController class]]) {
 45         if (self.lastSelectedViewContoller == vc) {
 46             [self.home refresh:YES];
 47         } else {
 48             [self.home refresh:NO];
 49         }
 50     }
 51     
 52     self.lastSelectedViewContoller = vc;
 53 }
 54 
 55 #pragma mark -- 得到未讀數
 56 
 57 - (void)getUnreadCount
 58 {
 59     // 1.請求參數
 60     HMUnreadCountParam *param = [HMUnreadCountParam param];
 61     param.uid = [HMAccountTool account].uid;
 62     
 63     // 2.得到未讀數
 64     [HMUserTool unreadCountWithParam:param success:^(HMUnreadCountResult *result) {
 65         // 顯示微博未讀數
 66         if (result.status == 0) {
 67             self.home.tabBarItem.badgeValue = nil;
 68         } else {
 69             self.home.tabBarItem.badgeValue = [NSString stringWithFormat:@"%d", result.status];
 70         }
 71         
 72         // 顯示消息未讀數
 73         if (result.messageCount == 0) {
 74             self.message.tabBarItem.badgeValue = nil;
 75         } else {
 76             self.message.tabBarItem.badgeValue = [NSString stringWithFormat:@"%d", result.messageCount];
 77         }
 78         
 79         // 顯示新粉絲數
 80         if (result.follower == 0) {
 81             self.profile.tabBarItem.badgeValue = nil;
 82         } else {
 83             self.profile.tabBarItem.badgeValue = [NSString stringWithFormat:@"%d", result.follower];
 84         }
 85         
 86         // 在圖標上顯示全部的未讀數
 87         [UIApplication sharedApplication].applicationIconBadgeNumber = result.totalCount;
 88         HMLog(@"總未讀數--%d", result.totalCount);
 89     } failure:^(NSError *error) {
 90         HMLog(@"得到未讀數失敗---%@", error);
 91     }];
 92 }
 93 
 94 /**
 95  *  建立自定義tabbar
 96  */
 97 - (void)addCustomTabBar
 98 {
 99     // 建立自定義tabbar
100     HMTabBar *customTabBar = [[HMTabBar alloc] init];
101     customTabBar.tabBarDelegate = self;
102     // 更換系統自帶的tabbar
103     [self setValue:customTabBar forKeyPath:@"tabBar"];
104 }
105 
106 /**
107  *  添加全部的子控制器
108  */
109 - (void)addAllChildVcs
110 {
111     HMHomeViewController *home = [[HMHomeViewController alloc] init];
112     [self addOneChlildVc:home title:@"首頁" imageName:@"tabbar_home" selectedImageName:@"tabbar_home_selected"];
113     self.home = home;
114     self.lastSelectedViewContoller = home;
115     
116     HMMessageViewController *message = [[HMMessageViewController alloc] init];
117     [self addOneChlildVc:message title:@"消息" imageName:@"tabbar_message_center" selectedImageName:@"tabbar_message_center_selected"];
118     self.message = message;
119     
120     HMDiscoverViewController *discover = [[HMDiscoverViewController alloc] init];
121     [self addOneChlildVc:discover title:@"發現" imageName:@"tabbar_discover" selectedImageName:@"tabbar_discover_selected"];
122     
123     HMProfileViewController *profile = [[HMProfileViewController alloc] init];
124     [self addOneChlildVc:profile title:@"" imageName:@"tabbar_profile" selectedImageName:@"tabbar_profile_selected"];
125     self.profile = profile;
126 }
127 
128 /**
129  *  添加一個子控制器
130  *
131  *  @param childVc           子控制器對象
132  *  @param title             標題
133  *  @param imageName         圖標
134  *  @param selectedImageName 選中的圖標
135  */
136 - (void)addOneChlildVc:(UIViewController *)childVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName
137 {
138     // 設置標題
139     childVc.title = title;
140     
141     // 設置圖標
142     childVc.tabBarItem.image = [UIImage imageWithName:imageName];
143     
144     // 設置tabBarItem的普通文字顏色
145     NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary];
146     textAttrs[NSForegroundColorAttributeName] = [UIColor blackColor];
147     textAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:10];
148     [childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal];
149     
150     // 設置tabBarItem的選中文字顏色
151     NSMutableDictionary *selectedTextAttrs = [NSMutableDictionary dictionary];
152     selectedTextAttrs[NSForegroundColorAttributeName] = [UIColor orangeColor];
153     [childVc.tabBarItem setTitleTextAttributes:selectedTextAttrs forState:UIControlStateSelected];
154     
155     // 設置選中的圖標
156     UIImage *selectedImage = [UIImage imageWithName:selectedImageName];
157     if (iOS7) {
158         // 聲明這張圖片用原圖(別渲染)
159         selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
160     }
161     childVc.tabBarItem.selectedImage = selectedImage;
162     
163     // 添加爲tabbar控制器的子控制器
164     HMNavigationController *nav = [[HMNavigationController alloc] initWithRootViewController:childVc];
165     [self addChildViewController:nav];
166 }
167 
168 #pragma mark - HMTabBarDelegate
169 - (void)tabBarDidClickedPlusButton:(HMTabBar *)tabBar
170 {
171     // 彈出發微博控制器
172     HMComposeViewController *compose = [[HMComposeViewController alloc] init];
173     HMNavigationController *nav = [[HMNavigationController alloc] initWithRootViewController:compose];
174     [self presentViewController:nav animated:YES completion:nil];
175 }
176 @end

 

3:封裝導航控制器的代碼:ide

#import <UIKit/UIKit.h>

@interface HMNavigationController : UINavigationController

@end
#import "HMNavigationController.h"

@interface HMNavigationController ()

@end

@implementation HMNavigationController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}
/**
 *  當導航控制器的view建立完畢就調用
 */
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 清空彈出手勢的代理,就能夠恢復彈出手勢
    self.interactivePopGestureRecognizer.delegate = nil;
}

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

/**
 *  設置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];
    // UITextAttributeFont  --> NSFontAttributeName(iOS7)
#warning 過時 : 並不表明不能用, 僅僅是有最新的方案能夠取代它
    textAttrs[UITextAttributeFont] = HMNavigationTitleFont;
    // 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];
}

/**
 *  能攔截全部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];
}

- (void)back
{
#warning 這裏用的是self, 由於self就是當前正在使用的導航控制器
    [self popViewControllerAnimated:YES];
}

- (void)more
{
    [self popToRootViewControllerAnimated:YES];
}
@end

4:封裝tabBar代碼:oop

#import <UIKit/UIKit.h>
@class HMTabBar;

@protocol HMTabBarDelegate <NSObject>

@optional
- (void)tabBarDidClickedPlusButton:(HMTabBar *)tabBar;

@end

@interface HMTabBar : UITabBar
@property (nonatomic, weak) id<HMTabBarDelegate> tabBarDelegate;
@end
#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.tabBarDelegate respondsToSelector:@selector(tabBarDidClickedPlusButton:)]) {
        [self.tabBarDelegate 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

5:封裝UIBarButtonItem:分類封裝佈局

//自定義圖片按鈕:常態,高亮狀態

#import <UIKit/UIKit.h>

@interface UIBarButtonItem (Extension)
+ (UIBarButtonItem *)itemWithImageName:(NSString *)imageName highImageName:(NSString *)highImageName target:(id)target action:(SEL)action;
@end
#import "UIBarButtonItem+Extension.h"

@implementation UIBarButtonItem (Extension)
+ (UIBarButtonItem *)itemWithImageName:(NSString *)imageName highImageName:(NSString *)highImageName target:(id)target action:(SEL)action
{
    UIButton *button = [[UIButton alloc] init];
    [button setBackgroundImage:[UIImage imageWithName:imageName] forState:UIControlStateNormal];
    [button setBackgroundImage:[UIImage imageWithName:highImageName] forState:UIControlStateHighlighted];
    
    // 設置按鈕的尺寸爲背景圖片的尺寸
    button.size = button.currentBackgroundImage.size;
    
    // 監聽按鈕點擊
    [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
    return [[UIBarButtonItem alloc] initWithCustomView:button];
}
@end

6:封裝UIView的frame:分類封裝字體

#import <UIKit/UIKit.h>

@interface UIView (Extension)
@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;
@property (nonatomic, assign) CGFloat centerX;
@property (nonatomic, assign) CGFloat centerY;
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) CGSize size;
@end
#import "UIView+Extension.h"

@implementation UIView (Extension)

- (void)setX:(CGFloat)x
{
    CGRect frame = self.frame;
    frame.origin.x = x;
    self.frame = frame;
}

- (CGFloat)x
{
    return self.frame.origin.x;
}

- (void)setY:(CGFloat)y
{
    CGRect frame = self.frame;
    frame.origin.y = y;
    self.frame = frame;
}

- (CGFloat)y
{
    return self.frame.origin.y;
}

- (void)setCenterX:(CGFloat)centerX
{
    CGPoint center = self.center;
    center.x = centerX;
    self.center = center;
}

- (CGFloat)centerX
{
    return self.center.x;
}

- (void)setCenterY:(CGFloat)centerY
{
    CGPoint center = self.center;
    center.y = centerY;
    self.center = center;
}

- (CGFloat)centerY
{
    return self.center.y;
}

- (void)setWidth:(CGFloat)width
{
    CGRect frame = self.frame;
    frame.size.width = width;
    self.frame = frame;
}

- (CGFloat)width
{
    return self.frame.size.width;
}

- (void)setHeight:(CGFloat)height
{
    CGRect frame = self.frame;
    frame.size.height = height;
    self.frame = frame;
}

- (CGFloat)height
{
    return self.frame.size.height;
}

- (void)setSize:(CGSize)size
{
//    self.width = size.width;
//    self.height = size.height;
    CGRect frame = self.frame;
    frame.size = size;
    self.frame = frame;
}

- (CGSize)size
{
    return self.frame.size;
}

@end

 

 

 

 

 

 

 

三:思路分析:ui

1:先添加首頁,信息,發現,我四個控制器爲根視圖控制器的子控制器,在viewDidload方法裏封裝方法[self addAllChildVcs];調用。由於四個子控制器中每一個子控制器都要設置title,Vc.tabBarItem.image,Vc.abBarItem.selectedImage,以及abBarItem的文字屬性,還要包裝一層導航控制器,最後addChildViewController做爲根視圖控制器的子控制器。此時會有大量重複的代碼,因此要想抽取代碼的思想,將大量重複的代碼抽成一個方法,把相同的代碼封裝在方法的內部,不一樣的部分做爲參數傳遞。因此將此段代碼抽成一個方法:- (void)addOneChlildVc:(UIViewController *)childVc title:(NSString *)title imageName:(NSString *)imageName selectedImageName:(NSString *)selectedImageName;建立出子控制器對象後,將子控制器對象,title,image ,selectedImage做爲參數傳遞。atom

2:設置tabItem的文字屬性:1:在封裝方法中,設置標題屬性, childVc.title = title;此句代碼既設置了tabBaritem上的標題,也設置了相應子控制器的導航欄的標題。設置tabBar上不一樣狀態下的標題的文字屬性:利用方法 setTitleTextAttributes:dic  forState:state 就能夠設置不一樣狀態下的文字屬性,常態,高亮,失效。(給字典賦值:dic[key]= value;dic爲可變字典)

    NSMutableDictionary *textAttrs = [NSMutableDictionary dictionary];

    textAttrs[NSForegroundColorAttributeName] = [UIColor blackColor];

    textAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:10];

    [childVc.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal];

 3:設置tabItem上不一樣狀態下的圖片屬性:1:Normal :childVc.tabBarItem.image = [UIImage imageWithName:imageName];  2:selected: UIImage *selectedImage = [UIImage imageWithName:selectedImageName];

    if (iOS7) {

        // 聲明這張圖片用原圖(別渲染)        selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];    }

    childVc.tabBarItem.selectedImage = selectedImage;

 注意:1:判斷是不是ios7,能夠在pch文件中作宏定義,其中一些宏定義,一些頭文件均可以在pch中作定義。

#define iOS7 ([[UIDevice currentDevice].systemVersion doubleValue] >= 7.0)

2:對於NSLog的宏定義也能夠在pch中:

1 #ifdef DEBUG  //調式狀態
2 #define DLog(...) NSLog (__VA_ARGS__)
3 #else //發佈狀態
4 #define DLog (...)
5 #endif

3:單例的宏定義:

//單例的宏定義:斜線向右,表示下一行也屬於宏定義
#define Single_interface(className)  +(className*)shared##className

#define Single_implemtation(className) +(className*)shared##className { \
\
static className *instance = nil;\
static dispatch_once_t onceToken;\
dispatch_once(&onceToken, ^{\
 \
    instance = [[self alloc]init];\
});\
\
return instance;\
}

4:在系統大於或等於ios7時,系統默認會對系統的一些控件產生渲染,渲染爲藍色,例如button爲系統樣式時,會被渲染爲藍色,而tabBarItem上的圖片,normal狀態下不會被渲染,只有是選中selected狀態下才會被渲染成藍色。解決辦法:三部曲:1:先建立圖片 2:判斷是否爲ios7如果則調用UIImage的方法imageWithRenderingMode,告訴系統不要渲染,保持原圖,並返回一張原圖的圖片。selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; 3:設置tabBarietm上的選中圖片 

 UIImage *selectedImage = [UIImage imageWithName:selectedImageName];
    if (iOS7) {
        // 聲明這張圖片用原圖(別渲染)
        selectedImage = [selectedImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
    }
    childVc.tabBarItem.selectedImage = selectedImage;

5:給每個子控制器包裝一層導航控制,主要自定義導航控制器,爲了設置導航控制器上item的屬性。新建類繼承UINavigationController。1:由於只要是自定義了導航控制器,則系統的側滑返回效果就會消失,只要在viewDidLoad裏將手勢代理清空便可:self.interactivePopGestureRecognizer.delegate = nil;

2:自定義UINavigationBar 和 UIBarButtonItem:1:其中UINavigationBar爲整個導航欄,設置其主體主要設置的是導航欄的背景色,背景圖片,title文字的屬性。UIBarButtonItem:設置的是導航欄上左右按鈕的圖片或是文字屬性。3:UINavigationBar *appearance = [UINavigationBar appearance];UIBarButtonItem *appearance = [UIBarButtonItem appearance];經過appearance方法返回的兩個對象是全局對象,經過設置這兩個對象的屬性,就能夠達到整個項目中全局設置,由於在整個項目中只須要設置一次,因此不須要在ViewDidload裏去設置,由於沒建立一次對象,ViewDidload就會調用一次,這樣導航欄的主題就會被重複設置,因此將設置導航欄主題的方法封裝在,+ (void)initialize,該方法只會在該類第一次使用,也就是該類的第一個方法被調用以前調用,有且只調用一次。在內部封裝的方法應爲類方法,用self去調用,在類方法中self指向的是當前的類,在對象方法中self指向的是當前的對象。

3:設置UINavigationBar屬性:得到全局導航欄對象appearance,1:能夠設置其背景色tintColor ,2:背景圖片:setBackgroundImage forBarMetrics: 第二個參數爲默認便可  2:設置title的文字屬性: [appearance setTitleTextAttributes:textAttrs];不用設置狀態。(在開發中有些方法是過時會有警告,其實也能用,只不過是有新的方法能夠代替它),設置title字體的偏移量也就是陰影效果,textAttrs[NSShadowAttributeName] = [NSValue valueWithUIOffset:UIOffsetZero];其中CGRect,CGPoint,UIOffset 都是結構體,只有封裝成NSValue對象,才能夠放到數組或是字典中。

4:設置UIBarButtonItem的主題:1:UIBarButtonItem也就是導航欄上的左右按鈕,能夠利用setTitleTextAttributes 

forState 屬性分別設置左右按鈕的常態,高亮,失效狀態下的文字屬性。2:當左右按鈕爲一張圖片時,給UIBarButtonItem寫一個分類,設置customView自定義按鈕,直接設置按鈕的背景圖片爲該張圖片就能夠。

5:重寫導航控制器的push方法:1:目的是攔截push方法,由於每一個棧裏的控制器,左右按鈕都相同,因此不須要再棧裏每一個控制器裏建立左右按鈕。攔截導航控制器的push方法,當壓棧的時候,就爲每一個即將壓棧的控制器設置了左右按鈕。2:在將四個主控制器包裝導航控制器的時候,initWithrootViewController,已經把該四個控制器壓入棧裏,此時會調用導航控制器的push方法,

/**
 *  能攔截全部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];
}

1:重寫的push方法,1:傳入的viewController爲即將壓棧的控制器,重寫系統的方法,不要忘記調用super。super方法在左後調用,是避免爲四個主控制器也設置左右按鈕 2:拿到導航控制器棧裏的子控制器數組:nav.viewControllers(self.viewControllers),判斷子控制器數組裏的控制器個數 > 0,則表示不是棧底控制器。此時能夠拿到即將壓棧的控制器設置左右item:viewController.navigationItem.leftBarButtonItem。2:對左右按鈕爲圖片的直接將圖片設置爲btn的背景圖片,給UIBarButtonItem寫一個分類,傳入normalImage ,HighlightedImage,target,action,自定義btn,設置不一樣狀態下的背景圖片,通常對於圖片按鈕來講,按鈕的大小就設置爲圖片的大小。對於button來講,得到當前的image,title,backgroundImage的方法,btn.currentTtitle,btn.currentImage,btn.currentBackgroundImage 3:若想調整左右按鈕距離屏幕的左右間距:能夠自定navbar繼承系統的bar,重寫layoutSubView方法,遍歷子控件數組,分別找到左右按鈕,調整左右按鈕的frame。再利用kvc的setValue forKeyPath,來替換掉系統的navBar(只需建立自定義bar的對象,由於繼承於系統,因此係統所聲明的非私有的屬性方法變量都會繼承,不用設置frame,第一個參數爲建立的自定義navbar對象,第二個參數爲導航控制器或是tabbar控制器下的navbar,或是tabbar以屬性定義的對象) 4:當push壓棧的時候,須要隱藏tabBar,此時可在攔截的push方法中,拿到即將壓棧的控制器,調用

  //0:當push的時候隱藏dock欄 viewController.hidesBottomBarWhenPushed = YES;

2:自定義tabBar的封裝:1:+(instancetype)tabBar;return [self alloc ]init]; 類方法快速返回一個對象,alloc內部會調用alloc initWithFrame方法,因此重寫alloc initWithFrame方法,在此方法內先設置自身的屬性:能夠設置tabbar的背景圖片self.backgroundImage 或是選中的背景圖片,self.selectionIndicatorImage = [UIImage imageWithName:@"navigationbar_button_background"];2:懶加載子控件,設置控件的屬性,將控件添加到父視圖上。建立中間的加號按鈕,常態,高亮狀態下的背景圖片,setImage設置常態高亮狀態下的圖片,添加監聽,添加到父視圖上。3:在layoutSubView裏設置控件的frame,(若爲圖片按鈕,有不一樣狀態,就設圖片爲整個按鈕背景,分貝設常態,高亮,選中狀態下的背景圖片,按鈕的大小爲圖片的大小:btn.currentTitle,btn.currentImage,btn.currentBackgroundImage便可得到當前顯示的圖片和標題。)如何拿到控件設置frame,1:屬性,成員變量,枚舉tag值 2:大數組思想:裝在大數組,當一個控件上分別有不一樣的控件的時候,能夠兩兩分別裝在數組裏,用到的時候再從數組裏取出 3:繼承UIView的能夠遍歷self.subViews,遍歷子控件的數組,作條件過濾,找到中止遍歷。如果UIScrollView,會多出兩個控件橫豎滾動條,直接隱藏就不會顯示了,隱藏後可直接遍歷子控件數組,也能夠提早給View設置tag值,當遍歷時,找到父view後,經過tag值將view取出 。當父view上有多個控件時,還能夠遍歷子控件數組,作過濾,當找到須要設置frame的控件後,須要根據index設置frame,此時在循環中沒法拿到index,就本身定義一個index,找到控件後執行index++,根據控件的索引來設置frame 4:設置按鈕的tag值:1:直接設置(可爲0)2:枚舉tag值,用於按鈕的回調,根據枚舉值判斷是哪一個按鈕 3:btn.tag =self.subViews.count,適用於將按鈕取出,或是應用於本類中 。4:因此設置加號按鈕的size爲圖片的size,經過btn.currentBackgroundImage把圖片取出(通常給系統控件賦值時,調用的是系統控件的set方法,若想在其餘地方得到該值,能夠調用其系統控件的get方法,例如btn的三個方法,lable.font,vc.title等),若是控件須要居中顯示的話,就設置控件的center屬性,例如新特性界面的pageControl的frame設置方法。5:雖然是自定義的tabBar,可是繼承的是系統的tabBar,已經添加了四個子控制器,因此自定義的tabbar上已經添加了四個按鈕。須要從新調整四個按鈕的距離。在layoutSubView裏從新調整四個按鈕的frame。遍歷子控件數組,作條件過濾,並打印,有的是系統沒有聲明的屬性,打印出只是一個字符串,利用NSSClassFromString();方法將字符串轉化爲類來判斷是否屬於.

/**
 *  設置全部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

設置frame的思路:1:tabBar上已經添加上了5個按鈕,就讓這5個按鈕評分tabBar的寬度,注意:self.ietms.count,雖然此時tabBar已經有5個按鈕了,可是個數爲4,它指的是加入tabBarcontroller中的子控制器的個數。高度爲自身tabBar的高度,y值爲0,x值的設置,前兩個能夠根據索引正常設置buttonW * index,到後兩個的時候:buttonW * (index + 1)。2:當在layoutSubView裏設置frame時,遍歷取出控件,根據index設置frame,若是沒法遍歷,能夠本身構造index,實現index++,將index傳過去。

5:tabBar點擊中間加號按鈕的回調:1:回調可用協議代理,block ,通知,前兩個用於層級較淺的回調,通知適用於層級較深的回調 2:其中兩個控制器須要回調數據時,若兩個控制器須要實時相互回調數據,可用block和協議代理,設置返回值,當一端回調數據後,處理完數據後,還能夠返回一些給原控制器提供回調數據。3:協議代理的方法默認爲@require,注意協議代書寫的規範性,仿照tableView的代理來設置

6:在tabBarController裏利用kvc替換系統的tabBar:不用設置frame

/**
 *  建立自定義tabbar
 */
- (void)addCustomTabBar
{
    // 建立自定義tabbar
    HMTabBar *customTabBar = [[HMTabBar alloc] init];
    customTabBar.tabBarDelegate = self;
    // 更換系統自帶的tabbar
    [self setValue:customTabBar forKeyPath:@"tabBar"];
}

7:UIImage的封裝:分類封裝

#import <UIKit/UIKit.h>

@interface UIImage (Extension)
/**
 *  根據圖片名自動加載適配iOS6\7的圖片
 */
+ (UIImage *)imageWithName:(NSString *)name;

/**
 *  根據圖片名返回一張可以自由拉伸的圖片
 */
+ (UIImage *)resizedImage:(NSString *)name;
@end
#import "UIImage+Extension.h"

@implementation UIImage (Extension)
+ (UIImage *)imageWithName:(NSString *)name
{
    UIImage *image = nil;
    if (iOS7) { // 處理iOS7的狀況
        NSString *newName = [name stringByAppendingString:@"_os7"];
        image = [UIImage imageNamed:newName];
    }
    
    if (image == nil) {
        image = [UIImage imageNamed:name];
    }
    return image;
}

+ (UIImage *)resizedImage:(NSString *)name
{
    UIImage *image = [UIImage imageWithName:name];
    return [image stretchableImageWithLeftCapWidth:image.size.width * 0.5 topCapHeight:image.size.height * 0.5];
}
@end

賦值代碼的三部曲:1:外部先定義一個變量 2:中間根據判斷條件拿到變量賦值 3:從新給變量賦值(若判斷條件不符合,則變量的值沒有改變,如果符合,則發生了改變)

相關文章
相關標籤/搜索