最終效果
1.tabBar 的基本信息設(shè)置
1.1 tabBarItem 的信息設(shè)置
UIViewController *vc = [[UIViewController alloc] init];
vc.tabBarItem.title = @"標(biāo)題";
vc.tabBarItem.image = [UIImage imageNamed:@"tabBar_new_icon"];
vc.tabBarItem.selectedImage = [UIImage imageNamed:@"tabBar_new_click_icon"];
vc.view.backgroundColor = [UIColor grayColor];
NSDictionary * attr = @{NSFont
AttributeName:[UIFont systemFontOfSize:12],NSForegroundColorAttributeName:[UIColor grayColor]};
[vc.tabBarItem setTitleTextAttributes:attrs forState:UIControlStateNormal];
NSDictionary * selectedAttrs = @{NSFontAttributeName:[UIFont systemFontOfSize:12],NSForegroundColorAttributeName:[UIColor darkGrayColor]};
[vc.tabBarItem setTitleTextAttributes:selectedAttrs forState:UIControlStateSelected];
[self addChildViewController:vc];
** 注意:**以上設(shè)置 tabBarItem 的 selectedImage 的方法,在實際運行過程中的效果與圖片本身的效果會有很大差異-----系統(tǒng)會默認(rèn)將選中圖片渲染成藍(lán)色展示
1.2 解決 tabBarItem 選中圖片渲染的問題
- 代碼解決
通過 UIImage的 imageWithRenderingMode 方法返回一個帶有渲染模式的圖片
- (UIImage *)imageWithRenderingMode:(UIImageRenderingMode)renderingMode ;
UIImageRenderingMode:
UIImageRenderingModeAutomatic // 根據(jù)圖片的使用環(huán)境和所處的繪圖上下文自動調(diào)整渲染模式捅僵。
UIImageRenderingModeAlwaysOriginal // 始終繪制圖片原始狀態(tài)下硕,不使用Tint Color涝涤。
UIImageRenderingModeAlwaysTemplate // 始終根據(jù)Tint Color繪制圖片饰及,忽略圖片的顏色信息。
UIImage *image = [UIImage imageNamed:imageName];
image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
vc.tabBarItem.selectedImage = image;
代碼解決的缺陷:代碼量繁瑣植榕,當(dāng)圖片用在另一個地方處理渲染效果時還需要再次設(shè)置
- 一次性設(shè)置---推薦使用
設(shè)置圖片渲染模式
1.3 appearance 設(shè)置文字屬性
在1.1的代碼中我們是通過下面方法粱腻,設(shè)置每一個item中文字的屬性的庇配。這種方法進行設(shè)置的話,需要對每一個item都進行設(shè)置栖疑,比較繁瑣
- (void)setTitleTextAttributes:(nullable NSDictionary<NSString *,id> *)attributes forState:(UIControlState)state NS_AVAILABLE_IOS(5_0) UI_APPEARANCE_SELECTOR;
- UIAppearance:通過UIAppearance設(shè)置一些UI的全局效果---實現(xiàn)一改全改的效果
// 通過appearance統(tǒng)一設(shè)置所有UITabBarItem的文字屬性
// 后面帶有UI_APPEARANCE_SELECTOR的方法, 都可以通過appearance對象來統(tǒng)一設(shè)置
[[UITabBarItem appearance] setTitleTextAttributes:attrs forState:UIControlStateNormal];
[[UITabBarItem appearance] setTitleTextAttributes:selectedAttrs forState:UIControlStateSelected];
2.自定義tabBar
2.1自定義控制器
創(chuàng)建繼承于 UIViewController 的控制器----不再贅述
2.2自定義TabBarController
創(chuàng)建繼承于 UITabBarController 的控制器
@interface ZZYTabBarViewController ()
@end
@implementation ZZYTabBarViewController
+ (void)initialize
{
//1讨永、設(shè)置UITabBarItem相關(guān)屬性
NSDictionary * attrs = @{NSForegroundColorAttributeName:[UIColor grayColor],NSFontAttributeName:[UIFont systemFontOfSize:12]};
NSDictionary * selectedAttrs = @{NSForegroundColorAttributeName:[UIColor darkGrayColor],NSFontAttributeName:[UIFont systemFontOfSize:12]};
UITabBarItem * item = [UITabBarItem appearance];
[item setTitleTextAttributes:attrs forState:UIControlStateNormal];
[item setTitleTextAttributes:selectedAttrs forState:UIControlStateSelected];
}
- (void)viewDidLoad {
[super viewDidLoad];
//2、初始化子控制器
[self setupChildVc:[[ZZYEssenceViewController alloc] init] title:@"精華" image:@"tabBar_essence_icon" selectedImage:@"tabBar_essence_click_icon"];
[self setupChildVc:[[ZZYNewViewController alloc] init] title:@"新帖" image:@"tabBar_new_icon" selectedImage:@"tabBar_new_click_icon"];
[self setupChildVc:[[ZZYFriendTrendsViewController alloc] init] title:@"關(guān)注" image:@"tabBar_friendTrends_icon" selectedImage:@"tabBar_friendTrends_click_icon"];
[self setupChildVc:[[ZZYMeViewController alloc] init] title:@"我" image:@"tabBar_me_icon" selectedImage:@"tabBar_me_click_icon"];
//3.自定義TabBar ----- 更換TabBar
[self setValue:[[ZZYTabBar alloc]init] forKeyPath:@"tabBar"];
// self.tabBar
}
- (void)setupChildVc:(UIViewController *)vc title:(NSString *)title image:(NSString *)image selectedImage:(NSString *)selectedImage
{
// 設(shè)置文字和圖片
vc.tabBarItem.title = title;
vc.tabBarItem.image = [UIImage imageNamed:image];
vc.tabBarItem.selectedImage = [UIImage imageNamed:selectedImage];
ZZYNavigationController * nav = [[ZZYNavigationController alloc]initWithRootViewController:vc];
// 添加為子控制器
[self addChildViewController:nav];
}
** 注意 :**
在設(shè)置自定義的 TabBar 時遇革,由于 tabBar 是系統(tǒng)默認(rèn) 只讀屬性卿闹,因此需要通過 KVC 語法揭糕,將自定義的 tabBar 對象,賦值給 tabBar 屬性即可
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
tabBar屬性
2.3 自定義TabBar
創(chuàng)建繼承于UITabBar 的 TabBar
#import "ZZYTabBar.h"
@interface ZZYTabBar()
/**
* 發(fā)布按鈕
*/
@property (nonatomic, weak) UIButton * publishButton;
@end
@implementation ZZYTabBar
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
UIButton *publishButton = [UIButton buttonWithType:UIButtonTypeCustom];
[publishButton setBackgroundImage:[UIImage imageNamed:@"tabBar_publish_icon"] forState:UIControlStateNormal];
[publishButton setBackgroundImage:[UIImage imageNamed:@"tabBar_publish_click_icon"] forState:UIControlStateHighlighted];
[self addSubview:publishButton];
self.publishButton = publishButton;
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
//設(shè)置發(fā)布按鈕的frame
注意此處設(shè)置 frame 時直接獲取 UIImage 對象寬高的方法
self.publishButton.bounds = CGRectMake(0, 0, self.publishButton.currentBackgroundImage.size.width, self.publishButton.currentBackgroundImage.size.height);
self.publishButton.center = CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5);
// 設(shè)置其他UITabBarButton的frame
CGFloat buttonY = 0;
CGFloat buttonW = self.frame.size.width / 5;
CGFloat buttonH = self.frame.size.height;
NSInteger index = 0;
for (UIView * button in self.subviews) {
if ([button isKindOfClass:NSClassFromString(@"UITabBarButton")])
{
//設(shè)置按鈕的x值---注意此處自定義的按鈕在中間锻霎,注意此處索引的處理
CGFloat buttonX = buttonW * ((index > 1)?(index + 1):index);
button.frame = CGRectMake(buttonX, buttonY, buttonW, buttonH);
// 增加索引
index++;
}
}
}
** 封裝控件基本步驟 **
- 在 initWithFrame:方法中添加子控件著角,提供便利構(gòu)造方法
- 在 layoutSubviews 方法中設(shè)置子控件的 frame(一定要調(diào)用 super 的 layoutSubviews )
- 增加模型屬性,在模型屬性 set 方法中設(shè)置數(shù)據(jù)到子控件上
2.4 對 Frame 進行封裝
通過創(chuàng)建 UIView 的分類來方便對 view 的frame 中width height 屬性的設(shè)置
#import <UIKit/UIKit.h>
@interface UIView (ZZYExtension)
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;
//- (CGFloat)x;
//- (void)setX:(CGFloat)x;
/** 在分類中聲明@property, 只會生成方法的聲明, 不會生成方法的實現(xiàn)和帶有_下劃線的成員變量*/
@end
#import "UIView+ZZYExtension.h"
@implementation UIView (ZZYExtension)
- (void)setWidth:(CGFloat)width
{
CGRect frame = self.frame;
frame.size.width = width;
self.frame = frame;
}
- (void)setHeight:(CGFloat)height{
CGRect frame = self.frame;
frame.size. height = height;
self.frame = frame;
}
- (void)setX:(CGFloat)x
{
CGRect frame = self.frame;
frame.origin.x = x;
self.frame = frame;
}
- (void)setY:(CGFloat)y
{
CGRect frame = self.frame;
frame.origin.y = y;
self.frame = frame;
}
- (CGFloat)width
{
return self.frame.size.width;
}
- (CGFloat)height
{
return self.frame.size.height;
}
- (CGFloat)x
{
return self.frame.origin.x;
}
- (CGFloat)y
{
return self.frame.origin.y;
}
@end
封裝后的按鈕 frame 設(shè)置代碼
- (void)layoutSubviews
{
[super layoutSubviews];
CGFloat width = self.width;
CGFloat height = self.height;
//設(shè)置發(fā)布按鈕的frame
self.publishButton.width = self.publishButton.currentBackgroundImage.size.width;
self.publishButton.height = self.publishButton.currentBackgroundImage.size.height;
self.publishButton.center = CGPointMake(width * 0.5, height * 0.5);
// 設(shè)置其他UITabBarButton的frame
CGFloat buttonY = 0;
CGFloat buttonW = width / 5;
CGFloat buttonH = height;
NSInteger index = 0;
//下面的與上面重復(fù)
}