一、项目的配置
1> 设置LaunchImage
然后再Assets.xcassets文件中就会出现Brand Assets,这就是LaunchImage!
2> 当不用SB时,点击SDK->General->Main Interface->删除Main
3> 修改项目在模拟器上名字:点击SDK->Info->Bundle name->然后点击修改即可,或者直接在info.plist文件中改也可以。
4>这个时候删除了SB,所以需要在AppDelegate中手动创建Window的根控制器
5>添加PCH
然后设置SDK->Build Settings->搜索Prefix Header->修改为$(SRCROOT)/项目名称/pch文件名
二、自定义TabBarController
1> 为了简化AppDelegate中的代码量,应该自定义TabBarController,将其添加内部的子控件代码封装起来。
// 创建window
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
// 设置根控制器
self.window.rootViewController = [[DSTabBarController alloc] init];
// 显示Window
[self.window makeKeyAndVisible];
2> 一次性修改UITabBarItem的属性,可以通过appearance来修改(提示:后面带有UI_APPEARANCE_SELECTOR的方法, 都可以通过appearance对象来统一设置)
+ (void)initialize
{
// 设置UITabBarItem的普通文字属性
UITabBarItem *appearance = [UITabBarItem appearance];
NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
attrs[NSForegroundColorAttributeName] = [UIColor grayColor];
[appearance setTitleTextAttributes:attrs forState:(UIControlStateNormal)];
// 选中文字属性
NSMutableDictionary *selectAttrs = [NSMutableDictionary dictionary];
selectAttrs[NSForegroundColorAttributeName] = [UIColor darkGrayColor];
[appearance setTitleTextAttributes:selectAttrs forState:(UIControlStateSelected)];
}
- (void)viewDidLoad {
[super viewDidLoad];
// 初始化子控制器
[self setupChildVc:[[DSEssenceViewController alloc] init] title:@"精华" image:@"tabBar_essence_icon" selectImage:@"tabBar_essence_click_icon"];
[self setupChildVc:[[DSNewViewController alloc] init] title:@"新帖" image:@"tabBar_new_icon" selectImage:@"tabBar_new_click_icon"];
[self setupChildVc:[[DSFriendTrendsViewController alloc] init] title:@"关注" image:@"tabBar_friendTrends_icon" selectImage:@"tabBar_friendTrends_click_icon"];
[self setupChildVc:[[DSMeViewController alloc] init] title:@"我的" image:@"tabBar_me_icon" selectImage:@"tabBar_me_click_icon"];
// 利用KVC修改readOnly属性来自定义TabBar
[self setValue:[[DSTabBar alloc] init] forKey:@"tabBar"];
}
3> 把设置子控件tabBarItem属性全部封装在一个方法中
1.关于图片渲染的问题(默认会变蓝色):
[[UIImage imageNamed:selectImage] imageWithRenderingMode:(UIImageRenderingModeAlwaysOriginal)];
- (void)setupChildVc:(UIViewController *)Vc title:(NSString *)title image:(NSString *)image selectImage:(NSString *)selectImage
{
Vc.tabBarItem.title = title;
Vc.tabBarItem.image = [UIImage imageNamed:image];
Vc.tabBarItem.selectedImage = [[UIImage imageNamed:selectImage] imageWithRenderingMode:(UIImageRenderingModeAlwaysOriginal)];
Vc.view.backgroundColor = DSRandomColor;
[self addChildViewController:Vc];
}
这个时候项目显示为:
接下来就需要添加中间的发帖按钮了!
三、自定义TabBar
1> 当需要修改TabBar里面子控件属性的时候,最直接的方法就是自定义TabBar,可以通过KVC来修改readOnly属性
[self setValue:[[DSTabBar alloc] init] forKey:@"tabBar"];
2> 在initWithFrame方法中添加发帖按钮(注意:不能再init方法中设置frame属性)
// 创建发帖按钮
UIButton *publishButton = [[UIButton alloc] init];
[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;
3> 在layoutSubviews方法中设置发帖按钮的frame以及内部子控件的位置
// 0.取得TbaBar宽高
CGFloat tabBarW = self.width;
CGFloat tabBarH = self.height;
// 1.设置发帖按钮的frame
self.publishButton.bounds = CGRectMake(0, 0, self.publishButton.currentBackgroundImage.size.width, self.publishButton.currentBackgroundImage.size.height);
self.publishButton.center = CGPointMake(tabBarW * 0.5, tabBarH * 0.5);
// 2.设置内部子控件的排布
CGFloat buttonY = 0;
CGFloat buttonW = tabBarW / 5;
CGFloat buttonH = tabBarH;
// 默认索引为0
NSInteger index = 0;
for (UIView *button in self.subviews) {
if ([button isKindOfClass:NSClassFromString(@"UITabBarButton")]) {
CGFloat buttonX = buttonW * ((index > 1)? (index + 1) : index);
button.frame = CGRectMake(buttonX, buttonY, buttonW, buttonH);
index++;
}
}
注意:tabBar里面的几个button的class就是UITabBarButton,但是属于私有类,可以通过NSClassFromString来获取该类的class
此时的项目截图:
四、设置导航栏
1> 因为每一个item的设置方式都是一样的,所以直接把设置代码封装到UIBarButtonItem分类中
+ (instancetype)itemWithImage:(NSString *)image highImage:(NSString *)highImage target:(id)target action:(SEL)action
{
UIButton *button = [[UIButton alloc] init];
[button setBackgroundImage:[UIImage imageNamed:image] forState:(UIControlStateNormal)];
[button setBackgroundImage:[UIImage imageNamed:highImage] forState:(UIControlStateHighlighted)];
button.size = button.currentBackgroundImage.size;
[button addTarget:target action:action forControlEvents:(UIControlEventTouchUpInside)];
return [[self alloc] initWithCustomView:button];
}
然后在viewDidLoad方法中设置就行。
2> 接下来就需要当push一个控制器的时候,设置当前控制器的返回item,所以就自定义导航控制器(创建tabbarController的子控制器代码中,将子控制器封装成导航控制器),重写push方法。设置返回按钮可以通过自定义item来实现(用按钮)
需要注意的是:
1.不能设置返回按钮为backBarButtonItem
2.要保证push进来的控制器不是第一个控制器,而且应该先设置返回按钮,并且隐藏底部TabBar,然后再调用系统的push方法(目的是让push进来的控制器可以设置leftItem)
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (self.viewControllers.count > 0) { // 如果push进来的不是第一个控制器
UIButton *backButton = [[UIButton alloc] init];
[backButton addTarget:self action:@selector(back) forControlEvents:(UIControlEventTouchUpInside)];
// 让按钮的内容超出-10距离
backButton.contentEdgeInsets = UIEdgeInsetsMake(0, -10, 0, 0);
// 让按钮内容在最左边
backButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
// 设置颜色
[backButton setTitleColor:[UIColor blackColor] forState:(UIControlStateNormal)];
[backButton setTitleColor:[UIColor redColor] forState:(UIControlStateHighlighted)];
// 设置图片和文字
[backButton setTitle:@"返回" forState:(UIControlStateNormal)];
[backButton setImage:[UIImage imageNamed:@"navigationButtonReturn"] forState:(UIControlStateNormal)];
[backButton setImage:[UIImage imageNamed:@"navigationButtonReturnClick"] forState:(UIControlStateHighlighted)];
backButton.bounds = CGRectMake(0, 0, 70, 30);
viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
// push进来后,隐藏底部tabbar
viewController.hidesBottomBarWhenPushed = YES;
}
// 这句代码要放在后面,让viewController可以覆盖上面设置的leftBarButtonItem
[super pushViewController:viewController animated:animated];
}
五、设置关注登录界面
这个界面主要用XIB描述的,需要注意的地方就是label的手动换行:Command + 回车
结语:到此第一天的总结就完成了,以下是整个项目的骨架!